Micronaut @Replaces 声明式客户端
Micronaut @Replaces with declarative Client
我将使用 Micronaut 文档(声明式 Http 客户端)中的代码 - 我正在使用 Spock
PetOperations.java
@Validated
public interface PetOperations {
@Post
Single<Pet> save(@NotBlank String name, @Min(1L) int age);
}
我有一个声明式客户端:
@Client("/pets")
public interface PetClient extends PetOperations {
@Override
Single<Pet> save(String name, int age);
}
我的目标是当我运行一个测试class,我想调用(@Replaces)另一个class(PetDummy) 而不是 PetClient,PetDummy class 位于我的测试文件夹
@Primary
@Replaces(PetClient.class)
@Singleton
public class PetDummy implements PetOperations {
@Override
public Single<Pet> save(String name, int age) {
Pet pet = new Pet();
pet.setName(name);
pet.setAge(age);
// save to database or something
return Single.just(pet);
}
}
测试class:
class PetTest extends Specification {
@Shared
@AutoCleanup
ApplicationContext applicationContext = ApplicationContext.run();
//EmbeddedServer server = applicationContext.getBean(EmbeddedServer.class).start();
PetClient client = applicationContext.getBean(PetOperations.class);
def 'test' (){
given: 'name and age'
when:
client.save("Hoppie", 1);
then:
noExceptionThrown()
}
}
然而,最后 PetClient 被调用,我也尝试过 @Factory 注释,但没有成功
PetClient extends PetOperations 和 PetDummy implements PetOperations,如果它们都实现了那么使用 @Replaces 就有意义了...
还有什么我可以尝试的吗?
谢谢!
另一期:
现在它可以工作了,PetClient 是我的 PetService 中的依赖项。当我测试我的 PetService 时,它仍然调用 PetClient 而不是 PetDummy。
我假设它与 applicationContext 有关,你会看到
宠物服务:
PetService {
@Inject
PetClient client;
buyFood(){
//...
Single<Pet> pet = client.save("Hoppie", 1));
}
}
每个服务测试:
class PetServiceTest extends ApplicationContextSpecification {
@Subject
@Shared
PetService petService = applicationContext.getBean(PetService)
PetOperations client = applicationContext.getBean(PetOperations.class) //client is not used here
def 'test' (){
given:
when:
petService.buyFood()
then:
noExceptionThrown()
}
}
我认为我需要从 PetService“进入”applicationContext,告诉“使用 PetDummy”实现(在测试中 class,因为 ApplicationContextSpecification 属于另一个模块
ApplicationContextSpecification 是:
abstract class ApplicationContextSpecification extends Specification implements ConfigurationFixture {
@AutoCleanup
@Shared
ApplicationContext applicationContext = ApplicationContext.run(configuration)
/* def cleanup() {
assert !hasLeakage()
}*/
}
ConfigurationFixture 包含数据库(休眠)的属性
您已经在检索 PetClient
bean 实现:
PetClient client = applicationContext.getBean(PetOperations.class);
如果使用适当的类型调用,应该提供替换虚拟 bean 实现:
PetOperations client = applicationContext.getBean(PetOperations.class);
我将使用 Micronaut 文档(声明式 Http 客户端)中的代码 - 我正在使用 Spock
PetOperations.java
@Validated
public interface PetOperations {
@Post
Single<Pet> save(@NotBlank String name, @Min(1L) int age);
}
我有一个声明式客户端:
@Client("/pets")
public interface PetClient extends PetOperations {
@Override
Single<Pet> save(String name, int age);
}
我的目标是当我运行一个测试class,我想调用(@Replaces)另一个class(PetDummy) 而不是 PetClient,PetDummy class 位于我的测试文件夹
@Primary
@Replaces(PetClient.class)
@Singleton
public class PetDummy implements PetOperations {
@Override
public Single<Pet> save(String name, int age) {
Pet pet = new Pet();
pet.setName(name);
pet.setAge(age);
// save to database or something
return Single.just(pet);
}
}
测试class:
class PetTest extends Specification {
@Shared
@AutoCleanup
ApplicationContext applicationContext = ApplicationContext.run();
//EmbeddedServer server = applicationContext.getBean(EmbeddedServer.class).start();
PetClient client = applicationContext.getBean(PetOperations.class);
def 'test' (){
given: 'name and age'
when:
client.save("Hoppie", 1);
then:
noExceptionThrown()
}
}
然而,最后 PetClient 被调用,我也尝试过 @Factory 注释,但没有成功
PetClient extends PetOperations 和 PetDummy implements PetOperations,如果它们都实现了那么使用 @Replaces 就有意义了...
还有什么我可以尝试的吗?
谢谢!
另一期:
现在它可以工作了,PetClient 是我的 PetService 中的依赖项。当我测试我的 PetService 时,它仍然调用 PetClient 而不是 PetDummy。
我假设它与 applicationContext 有关,你会看到
宠物服务:
PetService {
@Inject
PetClient client;
buyFood(){
//...
Single<Pet> pet = client.save("Hoppie", 1));
}
}
每个服务测试:
class PetServiceTest extends ApplicationContextSpecification {
@Subject
@Shared
PetService petService = applicationContext.getBean(PetService)
PetOperations client = applicationContext.getBean(PetOperations.class) //client is not used here
def 'test' (){
given:
when:
petService.buyFood()
then:
noExceptionThrown()
}
}
我认为我需要从 PetService“进入”applicationContext,告诉“使用 PetDummy”实现(在测试中 class,因为 ApplicationContextSpecification 属于另一个模块
ApplicationContextSpecification 是:
abstract class ApplicationContextSpecification extends Specification implements ConfigurationFixture {
@AutoCleanup
@Shared
ApplicationContext applicationContext = ApplicationContext.run(configuration)
/* def cleanup() {
assert !hasLeakage()
}*/
}
ConfigurationFixture 包含数据库(休眠)的属性
您已经在检索 PetClient
bean 实现:
PetClient client = applicationContext.getBean(PetOperations.class);
如果使用适当的类型调用,应该提供替换虚拟 bean 实现:
PetOperations client = applicationContext.getBean(PetOperations.class);