单元测试 WCMUsePOJO 类



我正在为扩展WCMUsePOJO的以下类编写单元测试用例。现在,这个类正在使用如下所示的getSlingScriptHelper方法。

public class ConstantsServiceProvider extends WCMUsePojo {
private static final Logger logger = LoggerFactory.getLogger(ConstantsServiceProvider.class);
private String var1;
@Override
public void activate() throws Exception {
ConstantsService constantsService = getSlingScriptHelper().getService(ConstantsService.class);
if(constantsService != null) {
var1  = constantsService.getVar1();
}
}
public string getVar1() { return var1; }
}

问题是我如何模拟getSlingScriptHelper方法?以下是我的单元测试代码。

public class ConstantsServiceProviderTest {

@Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
@Mock
public SlingScriptHelper scriptHelper;
public ConstantsServiceProviderTest() throws Exception {
}
@Before
public void setUp() throws Exception {
ConstantsService service = new ConstantsService();
scriptHelper = context.slingScriptHelper();
provider = new ConstantsServiceProvider();
provider.activate();
}
@Test
public void testGetvar1() throws Exception {
String testvar1 = "";
String var1 = provider.getVar1();
assertEquals(testvar1, var1);
}
} 

唯一应该"必须"*模拟的是SlingScriptHelper实例本身,以便它将模仿已声明服务的依赖注入。

其他所有内容(例如 Bindings 实例(都可以是具体的实现,例如:

import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.junit.Test;
import javax.script.Bindings;
import javax.script.SimpleBindings;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ConstantsServiceProviderTest {
private SlingScriptHelper mockSling = mock(SlingScriptHelper.class);
private ConstantsServiceProvider constantsServiceProvider = new ConstantsServiceProvider();
private Bindings bindings = new SimpleBindings();
@Test
public void testFoo() throws Exception {
//Arrange
final String expected = "Hello world";
final ConstantsService testConstantsService = new TestConstantsService(expected);
when(mockSling.getService(ConstantsService.class)).thenReturn(testConstantsService);
bindings.put(SlingBindings.SLING, mockSling);
//Act
constantsServiceProvider.init(bindings);
//Assert
final String actual = constantsServiceProvider.getVar1();
assertThat(actual, is(equalTo(expected)));
}
class TestConstantsService extends ConstantsService {
String var1 = "";
TestConstantsService(String var1) {
this.var1 = var1;
}
@Override
String getVar1() {
return var1;
}
}
}

正如你上面所说,这里的入口点是通过WCMUsePojo超类的init()方法(因为这个方法是Use.class接口的实现,这个测试结构也适用于通过该接口进行测试,即使你不直接使用 WCMUsePojo。

*这可以是任何类型的测试替身,不一定是模拟。

如果你想对ConstantsServiceProvider.class进行单元测试,就不应该为它创建一个模拟。相反,您应该创建其内部对象的模拟。所以:

  1. 使用new创建ConstantsServiceProvider的真实实例
  2. getSlingScriptHelper().getService(.)方法返回的模拟对象。通常,依赖项由某个容器(如Spring(提供(注入(到类,或者仅由应用的其他类使用 setter 提供。在这两种情况下,模拟创建都很容易。
  3. 如果您当前的实现不允许这样做 - 请考虑重构。
  4. 您正在测试void activate()不返回任何内容的方法。因此,您应该验证调用constantsService.getVar1()方法。

我强烈建议您学习Vogella单元测试教程

这是可能的解决方案之一。 主要思想是拥有类的真实对象,但使用覆盖getSlingScriptHelper()返回模拟scriptHelper

我也嘲笑了ConstantsService,但可能不需要,我不知道你的代码。

public class ConstantsServiceProviderTest {
@Mock
public SlingScriptHelper scriptHelper;
@Test
public void getVar1ReturnsActivatedValue() throws Exception {
// setup
final String expectedResult = "some value";
// Have a mocked ConstantsService, but if possible have a real instance.
final ConstantsService mockedConstantsService = 
Mockito.mock(ConstantsService.class);
Mockito.when(
mockedConstantsService.getVar1())
.thenReturn(expectedResult);
Mockito.when(
scriptHelper.getService(ConstantsService.class))
.thenReturn(mockedConstantsService);
// Have a real instance of your class under testing but with overridden getSlingScriptHelper()
final ConstantsServiceProvider providerWithMockedHelper =
new ConstantsServiceProvider() {
@Override
SlingScriptHelper getSlingScriptHelper() {
return scriptHelper;
}
};
// when
String actualResult = providerWithMockedHelper.getVar1();
// then
assertEquals(expectedResult, actualResult);
}
}

最新更新