Person.java
public class Person
{
private final Integer personID;
private final String personName;
public Person( Integer personID, String personName )
{
this.personID = personID;
this.personName = personName;
}
public Integer getPersonID()
{
return personID;
}
public String getPersonName()
{
return personName;
}
}
PersonDAO.java
public interface PersonDao
{
public Person fetchPerson( Integer personID );
public void update( Person person );
}
**PersonService.java**
public class PersonService
{
private final PersonDao personDao;
public PersonService( PersonDao personDao )
{
this.personDao = personDao;
}
public boolean update( Integer personId, String name )
{
Person person = personDao.fetchPerson( personId );
if( person != null )
{
Person updatedPerson = new Person( person.getPersonID(), name );
personDao.update( updatedPerson );
return true;
}
else
{
return false;
}
}
}
PersionServiceTest.java
public class PersonServiceTest
{
@Mock
private PersonDao personDAO;
private PersonService personService;
@Before
public void setUp()
throws Exception
{
MockitoAnnotations.initMocks( this );
personService = new PersonService( personDAO );
}
@Test
public void shouldUpdatePersonName()
{
Person person = new Person( 1, "Phillip" );
when( personDAO.fetchPerson( 1 ) ).thenReturn( person );
boolean updated = personService.update( 1, "David" );
assertTrue( updated );
verify( personDAO ).fetchPerson( 1 );
ArgumentCaptor<Person> personCaptor = ArgumentCaptor.forClass( Person.class );
verify( personDAO ).update( personCaptor.capture() );
Person updatedPerson = personCaptor.getValue();
assertEquals( "David", updatedPerson.getPersonName() );
// asserts that during the test, there are no other calls to the mock object.
verifyNoMoreInteractions( personDAO );
}
@Test
public void shouldNotUpdateIfPersonNotFound()
{
when( personDAO.fetchPerson( 1 ) ).thenReturn( null );
boolean updated = personService.update( 1, "David" );
assertFalse( updated );
verify( personDAO ).fetchPerson( 1 );
verifyZeroInteractions( personDAO );
verifyNoMoreInteractions( personDAO );
}
}
/*在上面的示例中,模拟的personDAO对象通过personService的构造函数(在personServiceTest类中)发送到personService类对象。
我的疑问是,如果没有任何setter或构造函数,如何将模拟的personDAO对象传递给personService类?
也就是说,如果personDAO是使用"new"创建的,而不是像下面代码中提到的那样从personService类中的构造函数或setter中获取。*/
public class PersonService
{
private final PersonDao personDao=new PersonDao();
public boolean update( Integer personId, String name )
{
Person person = personDao.fetchPerson( personId );
if( person != null )
{
Person updatedPerson = new Person( person.getPersonID(), name );
personDao.update( updatedPerson );
return true;
}
else
{
return false;
}
}
}
如何使用reflectiontestutils.setfield();
使用Mockito,可以通过使用@Mock
、@InjectMocks
和MockitoJUnitRunner
来实现。
这个问题描述如下:使用@Mock和@InjectMocks
记录一下,以下是JMockit 1.12:的测试类的样子
public class PersonServiceTest
{
@Tested PersonService personService;
@Mocked PersonDao personDAO;
@Test
public void shouldUpdatePersonName()
{
final Person person = new Person(1, "Phillip");
new NonStrictExpectations() {{
personDAO.fetchPerson(1); result = person; times = 1;
}};
boolean updated = personService.update(1, "David");
assertTrue(updated);
new FullVerifications() {{
Person updatedPerson;
personDAO.update(updatedPerson = withCapture());
assertEquals("David", updatedPerson.getPersonName());
}};
}
@Test
public void shouldNotUpdateIfPersonNotFound()
{
new Expectations() {{ personDAO.fetchPerson(1); result = null; }};
boolean updated = personService.update(1, "David");
assertFalse(updated);
}
}
通过对Mockito的大量搜索,我发现有两种类型的嘲讽:
- 代理模拟(通常的存根)
- 类重新映射(只有Jmockit支持)
你可以在这里阅读"模拟对象是如何工作的"。
对于我的问题,类重映射是的解决方案
另一种解决方案是通过使用InjectMocks
和ReflectionTestUtils
/* We can place this code in the JUnit test Class */
@Mock
PersonDAO personDAO;
@InjectMocks
PersonService personService;
@Before
public void setUP() {
MockitoAnnotations.init(this);
}
@Test
public void shouldUpdatePersonName(){
ReflectionTestutils.setField(personService,"personDao",personDAO);
............Remaining Code..........
}
ReflectionTestUtils
的作用是将personService
对象中的personDao
(使用"new"运算符创建)替换为本地创建的(使用@Mock
)mock personDAO
。
ReflectionTestutils.setField(target,"name",actual);
除了我能在网上提供的关于ReflectionTestUtils
的信息之外,还有很多信息。
我认为您的测试告诉您,数据库记录很难实现为不可修改的对象。
添加怎么样
Person updateName(String name);
到Person类?