Last active
August 29, 2015 14:23
-
-
Save thekalinga/c55b652cc9cd6831608e to your computer and use it in GitHub Desktop.
Blind vision for integration testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@RunWith(JUnit4.class) | |
// Mockito + Spring integration/ use native @InjectMocks of mockito | |
@EnableMockedBean | |
// Spring MVC test configuration | |
@ContextConfiguration | |
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, | |
DirtiesContextTestExecutionListener.class, | |
TransactionalTestExecutionListener.class, | |
// DBUnit & Spring integration | |
DbUnitTestExecutionListener.class }) | |
// PowerMock | |
@PrepareForTest( { CustomUtil.class }) | |
class GuineaPigResourceTests { | |
// Assumption is that all these would hook into the lifecycle in the order in which these are specified | |
// All these rules might needs to be collated in some form | |
// Does not exist yet as for as I know | |
@Rule | |
NestedRunner nestedRunner = new NestedRunner(); | |
// Spring rules, exist in > 4.2 | |
@ClassRule | |
static SpringClassRule SPRING_CLASS_RULE = new SpringClassRule(); | |
@Rule | |
SpringMethodRule springMethodRule = new SpringMethodRule(); | |
// Does not exist yet as for as I know | |
@Rule | |
JunitParamsRunner junitParamsRunner = new JunitParamsRunner(); | |
// Does not exist yet as for as I know | |
@Rule | |
AssumesRunner assumesRunner = new AssumesRunner(); | |
// Exists in the latest beta of Mockito | |
@Rule | |
MockitoRule rule = MockitoJUnit.rule(); | |
// Already present | |
@Rule | |
PowerMockRule rule = new PowerMockRule(); | |
// Global vars | |
// This mocked bean is already injected into GuineaPigService by the therore-spring-mockito library, whcih you can use to set expectations | |
@MockedBean | |
private EmailService emailService; | |
@Resource | |
private WebApplicationContext webApplicationContext; | |
private MockMvc mockMvc; | |
@Before | |
void setUp() { | |
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); | |
} | |
public class AddNewGuineaPig { | |
@Before | |
public void setup() {} | |
@Test | |
@Params(method = "validGuineaPigsProvider") | |
void withValidValues_ShouldSave(GuineaPig guineaPig) { | |
// we can even capture this argument using arguments captor and verify at the end | |
when(emailService.send(anyObject())); | |
when(CustomUtil.validateImage(ayString())).thenReturn(true); // power mockito | |
mockMvc.perform( | |
post("/") | |
.content(guineaPig) | |
.accepts(MediaType.APPLICATION_JSON).. | |
) | |
.andExpect(status().isOk()) | |
.andExpect(jsonPath("$.id", is(notNull()))) | |
.andExpect(jsonPath("$.name", is(guineaPig.getName()))); | |
// we may want to do a get on the new id and verify | |
// Mockito verify | |
verify(emailService.times(1)); | |
verify(validateImage()).times(1); | |
} | |
@Test | |
// This test only makes sense after the save is successful, if its not succeeding lets skip this test altogeather | |
@Assumes(method = "withValidValues_ShouldSave") | |
void afterSave_EmailMessageHasCorrectSender() { | |
// do additional cerifications | |
} | |
@Test | |
@Params(method = "invalidGuineaPigsProvider") | |
void withInvalidData_ShouldReturnUnProcessableEntity(GuineaPig guineaPig) { | |
mockMvc.perform( | |
post("/") | |
.content(guineaPig) | |
.accepts(MediaType.APPLICATION_JSON) | |
) | |
.andExpect(status().is422()); | |
// Mockito verify that email is not sent | |
verify(emailService.none()); | |
} | |
@Test | |
// DBUnit to populate some existing guinnea pigs | |
@DatabaseSetup("GuineaPigs.xml") | |
void withNonUniqueProperty_ShouldReturnUnProcessableEntity() { | |
GuineaPig guineaPigWithDuplicateLicenseNumber = new GuineaPig.Builder()....build(); | |
mockMvc.perform( | |
post("/") | |
.content(guineaPigWithDuplicateLicenseNumber) | |
.accepts(MediaType.APPLICATION_JSON) | |
) | |
.andExpect(status().is422()); | |
// Mockito verify that email is not sent | |
verify(emailService.none()); | |
} | |
private GuineaPig[] validGuineaPigsProvider() { | |
// or read from the file | |
return new GuineaPig[] { | |
new GuineaPig.Builder().name("Name").breed("Breed").description("Desc").build(), | |
new GuineaPig.Builder().name("SomeOtherName").breed("Breed").description("Desc").build() | |
}; | |
} | |
private GuineaPig[] invalidGuineaPigsProvider() { | |
// or read from the file | |
return new GuineaPig[] { | |
new GuineaPig.Builder().name("").breed("Breed").description("Desc").build(), | |
new GuineaPig.Builder().name("Toooooooooooooooooooo Longggggggggg").breed("Breed").description("Desc").build() | |
}; | |
} | |
} | |
} | |
@RestController | |
@RequestMapping(consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE) | |
class GuineaPigResource { | |
@Autowired | |
GuineaPigService guineaPigService; | |
@RequestMapping(method=POST) | |
GuineaPig save(GuineaPig pig) { | |
return guineaPigService.save(pig); | |
} | |
} | |
interface GuineaPigService { | |
GuineaPig save(GuineaPig pig); | |
} | |
class GuineaPigServiceImpl implements GuineaPigService { | |
@Autowired | |
EmailService emailService; | |
GuineaPig save(GuineaPig pig) { | |
// Save using DAO | |
// Storing the image in db is clearly a bad idea, this is here to illustrate the example | |
CustomUtil.validateImage(pig.imageAsBase64); | |
// construct emailMessage | |
emailService.send(emailMessage); | |
} | |
} | |
interface EmailService { | |
void send(Message message); | |
} | |
class SendMailEmailService implements EmailService { | |
void send(Message message) { | |
// send using SendMail service | |
} | |
} | |
@Builder | |
@AllArgsConstructor | |
class GuineaPig { | |
// name validation rules | |
// 1. name length must be between 2-10 chars | |
// 2. name must be alphabets only | |
// 3. other rules | |
String name; | |
String uniquePropery; | |
String breed; | |
String image; | |
String description; // optional | |
} | |
class CustomUtil { | |
private CustomUtil() {} | |
static void validateImage() { | |
// has constaints like running in a specific env/takes a long time to compute | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment