Eclipse Scout Neon 模拟后端服务
Eclipse Scout Neon mock backend service
在我们的项目中,我有模块 scout.client、scout.server、scout.shared 和后端。
后端不依赖于 scout.server 和 scout.shared,但是 scout.server 依赖于后端。
在后端项目中,我拥有所有业务逻辑并调用所有外部服务。
我的问题是当我尝试测试使用后端某些服务的 scout 服务时。
因为 scout 提供了一些很棒的模拟 bean 的工具,我们将我们的后端服务定义为 beans 如下:
BEANS.getBeanManager().registerClass(CarService.class);
BEANS.getBeanManager().registerClass(PartnerService.class);
CarService.class 和 PartnerService.class 都在后端。
当我尝试编写一些测试时,我将@BeanMock 添加到测试服务中
@BeanMock
private IPartnerService partnerService;
我得到了模拟,但是每个 return 每个函数都是空的,即使我写
doReturn(PartnerBuilder.standardPartnerListWithOneElement()).when(this.partnerService)
.getPartners(any(Set.class));
如果我在我的测试中调试,在使用调试器调用这个测试之前我可以得到:
partnerService.getPartners(...) -> return a list of person
什么是对的,但是当被测试的class调用这个服务时它return null。
我知道这可能是由于接口 @ApplicationScoped
上缺少注释所致。如果没有这个,就不能保证只创建一个 bean
,并且 when
语句对该 bean 的另一个副本做出反应...?
我无法在接口上添加注释,因为后端不依赖于 scout 模块。
遇到这种情况怎么办?
测试class是:
public class UtilityPartner {
/**
* Method return service bean for getting partners by ids.
*
* @return
*/
private static IPartnerService getPartnerService() {
return BEANS.get(IPartnerService.class);
}
public static String getPartnerName(final Long partnerId) {
if (partnerId == null) {
return "";
}
final List<Partner> partners =
(List<Partner>) getPartnerService().getPartners(Sets.newHashSet(partnerId));
if (partners == null || partners.isEmpty()) {
return "";
}
final Partner partner = partners.get(0);
return LookupUtil.createLookupDescription(partner.getId(), partner.getName());
}
}
测试 class 是:
@RunWith(ServerTestRunner.class)
@RunWithSubject("anonymous")
@RunWithServerSession(ServerSession.class)
public class TestUtilityPartner {
@BeanMock
private IPartnerService partnerService;
@Before
public void init() {
doReturn(PartnerBuilder.standardPartnerListWithOneElement()).when(this.partnerService).getPartners(any(Set.class));
}
@Test
public void getPartnerName() {
final String name = UtilityPartner.getPartnerName(10L);
Assert.assertEquals("My name", name); // NAME IS ""
}
}
我认为您应该在 Bean 管理器中注册您的 mock 实例(请参阅 bean registration in the Scout Architecture Document). You should use a small order (-10 000 is recommended for tests),以便您的 mock 赢得生产性注册。最好的方法是使用 TestingUtility
class 到 register/unregister 你的模拟。不要忘记调用 unregisterBean()
方法(在用 @After
注释的方法中):
import java.util.Collections;
import org.eclipse.scout.rt.platform.BeanMetaData;
import org.eclipse.scout.rt.platform.IBean;
import org.eclipse.scout.rt.testing.shared.TestingUtility;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestUtilityPartner {
private IBean<?> beanRegistration;
@Before
public void init() {
partnerService = Mockito.mock(IPartnerService.class);
// Register the mock using the Bean meta information:
BeanMetaData beanData = new BeanMetaData(IPartnerService.class)
.withInitialInstance(partnerService)
.withApplicationScoped(true);
this.beanRegistration = TestingUtility.registerBean(beanData);
// Mockito behavior:
Mockito.doReturn(Collections.singletonList(new Partner(34L, "John Smith")))
.when(partnerService).getPartners(Mockito.any(Set.class));
}
@After
public void after() {
// Unregister the mocked services:
TestingUtility.unregisterBean(this.beanRegistration);
}
@Test
public void getPartnerName() {
String name = UtilityPartner.getPartnerName(10L);
Assert.assertEquals("10 - John Smith", name);
}
}
我不确定 @BeanMock
(org.eclipse.scout.rt.testing.platform.mock.BeanMock
) 在做什么,但根据 它不会起作用:
Using @BeanMock
does not help here, because you are not using an application scoped service:
In the init method you are changing the local field partnerService. However, in your test you call UtilityPartner.getPartnerService, which is creating a new instance (with BEANS.get(IPartnerService.class)
).
@BeanMock
is more useful for convenience for mocking application scoped beans.
使用 @BeanMock
在这里没有帮助,因为您没有使用应用程序范围的服务:
在 init 方法中,您正在更改本地字段 partnerService。但是,在您的测试中,您调用了 UtilityPartner.getPartnerService,它正在创建一个新实例(使用 BEANS.get(IPartnerService.class)
)。
@BeanMock
对于模拟应用程序作用域 bean 的便利性更有用。
您始终可以手动注册您的 bean 。请不要忘记在测试后再次注销bean!
我们建议使用 org.eclipse.scout.rt.testing.shared.TestingUtility.registerBean(BeanMetaData)
,它会自动添加测试订单并删除 @TunnelToServer
注释。
在我们的项目中,我有模块 scout.client、scout.server、scout.shared 和后端。
后端不依赖于 scout.server 和 scout.shared,但是 scout.server 依赖于后端。
在后端项目中,我拥有所有业务逻辑并调用所有外部服务。
我的问题是当我尝试测试使用后端某些服务的 scout 服务时。
因为 scout 提供了一些很棒的模拟 bean 的工具,我们将我们的后端服务定义为 beans 如下:
BEANS.getBeanManager().registerClass(CarService.class);
BEANS.getBeanManager().registerClass(PartnerService.class);
CarService.class 和 PartnerService.class 都在后端。
当我尝试编写一些测试时,我将@BeanMock 添加到测试服务中
@BeanMock
private IPartnerService partnerService;
我得到了模拟,但是每个 return 每个函数都是空的,即使我写
doReturn(PartnerBuilder.standardPartnerListWithOneElement()).when(this.partnerService)
.getPartners(any(Set.class));
如果我在我的测试中调试,在使用调试器调用这个测试之前我可以得到:
partnerService.getPartners(...) -> return a list of person
什么是对的,但是当被测试的class调用这个服务时它return null。
我知道这可能是由于接口 @ApplicationScoped
上缺少注释所致。如果没有这个,就不能保证只创建一个 bean
,并且 when
语句对该 bean 的另一个副本做出反应...?
我无法在接口上添加注释,因为后端不依赖于 scout 模块。
遇到这种情况怎么办?
测试class是:
public class UtilityPartner {
/**
* Method return service bean for getting partners by ids.
*
* @return
*/
private static IPartnerService getPartnerService() {
return BEANS.get(IPartnerService.class);
}
public static String getPartnerName(final Long partnerId) {
if (partnerId == null) {
return "";
}
final List<Partner> partners =
(List<Partner>) getPartnerService().getPartners(Sets.newHashSet(partnerId));
if (partners == null || partners.isEmpty()) {
return "";
}
final Partner partner = partners.get(0);
return LookupUtil.createLookupDescription(partner.getId(), partner.getName());
}
}
测试 class 是:
@RunWith(ServerTestRunner.class)
@RunWithSubject("anonymous")
@RunWithServerSession(ServerSession.class)
public class TestUtilityPartner {
@BeanMock
private IPartnerService partnerService;
@Before
public void init() {
doReturn(PartnerBuilder.standardPartnerListWithOneElement()).when(this.partnerService).getPartners(any(Set.class));
}
@Test
public void getPartnerName() {
final String name = UtilityPartner.getPartnerName(10L);
Assert.assertEquals("My name", name); // NAME IS ""
}
}
我认为您应该在 Bean 管理器中注册您的 mock 实例(请参阅 bean registration in the Scout Architecture Document). You should use a small order (-10 000 is recommended for tests),以便您的 mock 赢得生产性注册。最好的方法是使用 TestingUtility
class 到 register/unregister 你的模拟。不要忘记调用 unregisterBean()
方法(在用 @After
注释的方法中):
import java.util.Collections;
import org.eclipse.scout.rt.platform.BeanMetaData;
import org.eclipse.scout.rt.platform.IBean;
import org.eclipse.scout.rt.testing.shared.TestingUtility;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestUtilityPartner {
private IBean<?> beanRegistration;
@Before
public void init() {
partnerService = Mockito.mock(IPartnerService.class);
// Register the mock using the Bean meta information:
BeanMetaData beanData = new BeanMetaData(IPartnerService.class)
.withInitialInstance(partnerService)
.withApplicationScoped(true);
this.beanRegistration = TestingUtility.registerBean(beanData);
// Mockito behavior:
Mockito.doReturn(Collections.singletonList(new Partner(34L, "John Smith")))
.when(partnerService).getPartners(Mockito.any(Set.class));
}
@After
public void after() {
// Unregister the mocked services:
TestingUtility.unregisterBean(this.beanRegistration);
}
@Test
public void getPartnerName() {
String name = UtilityPartner.getPartnerName(10L);
Assert.assertEquals("10 - John Smith", name);
}
}
我不确定 @BeanMock
(org.eclipse.scout.rt.testing.platform.mock.BeanMock
) 在做什么,但根据
Using
@BeanMock
does not help here, because you are not using an application scoped service:In the init method you are changing the local field partnerService. However, in your test you call UtilityPartner.getPartnerService, which is creating a new instance (with
BEANS.get(IPartnerService.class)
).
@BeanMock
is more useful for convenience for mocking application scoped beans.
使用 @BeanMock
在这里没有帮助,因为您没有使用应用程序范围的服务:
在 init 方法中,您正在更改本地字段 partnerService。但是,在您的测试中,您调用了 UtilityPartner.getPartnerService,它正在创建一个新实例(使用 BEANS.get(IPartnerService.class)
)。
@BeanMock
对于模拟应用程序作用域 bean 的便利性更有用。
您始终可以手动注册您的 bean
我们建议使用 org.eclipse.scout.rt.testing.shared.TestingUtility.registerBean(BeanMetaData)
,它会自动添加测试订单并删除 @TunnelToServer
注释。