【问题标题】:Unit testing a class that relies on an EJB and UserTransaction对依赖于 EJB 和 UserTransaction 的类进行单元测试
【发布时间】:2015-07-20 17:23:06
【问题描述】:

如何为接受 EJBContext 对象的类编写单元测试? 即

public class MyProcessor {    

public MyProcessor (EJBContext ejbContext, SomePojo somePojo) { }

    ReturnObject saveMethod(InputObject inputObject){
         UserTransaction utx = this.context.getUserTransaction();

          try {
             utx.begin();
             ....
             ....
              }
     return ReturnObject;
    }
}

我正在使用 mockito 和 Junit。我已经学习了很多初学者教程,但找不到任何关于我想测试的课程的可靠信息。

到目前为止,我已经通过了:

@Mock
@RunWith(MockitoJUnitRunner.class)
public class MyProcessorTest{

@Mock
MyProcessor myProcessor;

    @Test
public void testSaveNewAssignment() {   

    InputObject inputObject= new InputObject();

    ReturnObject returnObject = new ReturnObject();

    when(myProcessor.saveMethod(inputObject)).thenReturn(returnObject);

    ReturnObject actualReturnObject= myProcessor.saveMethod(inputObject);

    assertSame(returnObject, actualReturnObject);

}

我不确定这实际上在做什么,以及这是否是正确的方法。

许多 mockito 示例使用“new”关键字来实例化我正在测试的类。但是当我在 MyProcessor 上调用 new 关键字时,我猜想模拟出 EJBContext 和 SomePojo,但我得到一个 java.lang.NullPointerException 当我这样做时,UserTransaction utx 中的错误。

更新: 感谢 RadekSohlich 的回答,我使用了 InjectMocks 注释并且没有使我的处理器类成为我正在做的模拟(当然是不正确的)。

发生的另一件有趣的事情是我必须模拟 UserTransaction,并使用 Mockito 的“when”关键字告诉它使用该模拟。否则我会有一个 nullpointerException。

这是一个有效的解决方案示例:

@RunWith(MockitoJUnitRunner.class)
public class MyProcessorTest {

@Mock
private InputObject inputObject

@Mock
private UserTransaction utx;

@Mock
private EJBContext context;

@Mock
private SomePojo somePojo

@InjectMocks    
private MyProcessor myProcessor;

public MyProcessorTest() {
}

@Before
public void setUp() throws Exception {

MockitoAnnotations.initMocks(this);

when(context.getUserTransaction()).thenReturn(utx);
}

@Test
public void testSaveNewAssignment_instantiate() {

    ReturnObject response = myProcessor.saveMethod(inputObject);

    // no exception encountered
    assertTrue(true);
  }
}

【问题讨论】:

  • 测试 EJB 并不简单。项目Arquillian 真的可以帮助你。有了这个,您可以直接在应用程序服务器环境中测试 bean。不幸的是,您将处理所选服务器的特定功能。
  • 谢谢,在任何其他情况下我都会使用 Arquillian,但是我们被这个很难设置 Arquillian 的特殊 IDE 卡住了。如果我们要使用 Eclipse,那肯定是的。

标签: unit-testing junit mocking ejb mockito


【解决方案1】:

关键是对你的测试bean依赖的对象/bean使用注解@Mock。例如,我正在测试类AssignmentRest,它依赖于AssignmentRepository、FileRepository、SubmissionHelper 和PluginService 类,因此您必须模拟所有bean 并为被测bean 使用注释@InjectMocks。见例子:

public class AssignmentRestTest extends GenericTest {

@Mock AssignmentRepository assignmentRepo;
@Mock FileRepository fileRepo;
@Mock SubmissionHelper submissionHelper;
@Mock PluginService pluginHolder;

@InjectMocks AssignmentRest assignRest;

public AssignmentRestTest() throws IOException {
    super();
}

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
    mockMvc = MockMvcBuilders.standaloneSetup(assignRest).build();
    RestAssuredMockMvc.mockMvc = mockMvc;
    presetBeans();
}

public void presetBeans() {
    //Preset the return values
    Mockito.when(pluginHolder.isSupportedLang(anyString())).thenReturn(Boolean.TRUE);
    Mockito.when(assignmentRepo.save(any(Assignment.class))).thenReturn(new Assignment("1234", "rada", "C", "Test", "NEW", new Date()));
}

@Test
public void testCreateAssignment() {
    given().body("{\"owner\":\"rada\",\"name\": \"CHistory\",\"lang\": \"C\",\"assignmentId\": \"0\"}")
            .contentType("application/json")
            .when().
            post("/rest/assignment/create").
            then().
            statusCode(HttpServletResponse.SC_OK);
}


@Test
public void testGetAll(){
given().
            when().
            get("/rest/assignment/all/rada").
            then().
            statusCode(HttpServletResponse.SC_OK);
}

}

【讨论】:

  • 谢谢,这真的很好用。 InjectMocks 注释是我正在寻找的关键。
  • @ArmandoPerea,如果成功了,也许你可以将其标记为答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多