I am a newbie learning spring mvc with portlets. I have a controller which returns the view. I am not sure how to write the unit test that controller.
#controller
#RequestMapping("VIEW")
public class HelloController {
#ResourceMapping(value = "hello")
public String helloWorld(RenderRequest request) {
return "hello";
}
and my Unit Test controller is something like this
public class HelloWorldControllerTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testHelloWorldController() throws IOException {
MockRenderRequest request = new MockRenderRequest();
HelloController c = new HelloController ();
ModelAndView result = c.helloWorld(request);
assertNotNull("ModelAndView should not be null", result);
assertEquals("hello", result.getViewName());
}
This is not working as the result is not a ModelAndView object but it is a String in the controller. The return type can be a ModelAndView object in the main controller but if using spring annotation based then from the examples I have found the return type is String. Can anyone suggest which is the best practice or if I am wrong in understanding.
Thanks in advance
The spring-test-mvc project facilitates testing Spring MVC controllers.
Checkout spring-test-portlet-mvc (https://github.com/markusf/spring-test-portlet-mvc) to integration test your Spring controllers.
Related
I have a service class, with for readability purpose, I have provided the code with dummy variables and objects. I am trying to write a JUNIT test class for the service, primarily with Mockito. No matter how hard I try, I am not able to hit the method serviceMethod irrespective of using spy/mock. I have also included a test, following the main class.
I know I am missing something here, but doesn't cross my mind. I need an eye to review this and let me know how I can write a proper test class for this and obtain coverage for the method.
(P.S. all the necessary imports are in-place and not pasted here to keep this concise)
Thanks in advance!
#Service
public class ServiceClass {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceClass.class);
#Autowired
String stringUrl;
RestTemplate restTemplate = new RestTemplate();
public void serviceMethod(ModelObject model) {
try {
HttpEntity<ModelObject> request = new HttpEntity<>(model);
ResponseEntity<String> response = restTemplate.exchange(stringUrl,
HttpMethod.POST, request, String.class);
LOGGER.info(response.getBody() + "and " + response.getStatusCode());
} catch (HttpClientErrorException exception) {
LOGGER.info(exception.getResponseBodyAsString());
} catch (HttpStatusCodeException exception) {
LOGGER.info(exception.getResponseBodyAsString());
}
}
Sample Test:
#RunWith(MockitoJUnitRunner.Silent.class)
public class ServiceClassTest {
#InjectMocks
private ServiceClass serviceClass;
#Mock
private RestTemplate restTemplate;
#Test
public void testServiceMethod() {
ServiceClass spy = Mockito.spy(serviceClass);
// ServiceClass spy = mock(ServiceClass.class, Mockito.CALLS_REAL_METHODS);
doNothing().when(spy).serviceMethod(Mockito.any(ModelObject.class));
Mockito.doCallRealMethod().when(spy).serviceMethod(Mockito.any(ModelObject.class));
ResponseEntity<String> responseEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
Mockito.when(restTemplate.exchange(ArgumentMatchers.anyString(), ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.<HttpEntity<ModelObject>>any(), ArgumentMatchers.<Class<String>>any()))
.thenReturn(responseEntity);
}
I am using Apache Camel with Spring boot in my application. Currently I am working on a Unit test.
Java Code
DataRoute class
from("direct:getData")
.routeId("getData")
.bean(DataService.class, "processData")
.marshal().json(JsonLibrary.Jackson)
.end();
DataService class
public Data processData() {
return new Data("Hello World");
}
Data Class with getters, setters and Jackson toString method
private String value;
Unit test
BaseCamelContextUnitText
public abstract class BaseCamelContextUnitTest extends CamelTestSupport
{
#Autowired
private DataService dataService;
#Produce
private ProducerTemplate producerTemplate;
public CamelContext getCamelContext() {
return camelContext;
}
#Override
protected Context createJndiContext() throws Exception {
JndiContext context = new JndiContext();
context.bind("dataService", dataService);
return context;
}
#Test
public void shouldProcessData() throws Exception {
RouteDefinition routeDef = getCamelContext().getRouteDefinition("getData");
routeDef.adviceWith((ModelCamelContext) getCamelContext(), new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:getData")
.pipeline("bean:dataService?method=processData");
}
});
getCamelContext().start();
String responseData = "{"
+ "\"value\":\"Unit test success\""
+ "}";
Object response = producerTemplate.sendBody("direct:getData", ExchangePattern.InOut, null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
((InputStreamCache) response).writeTo(byteArrayOutputStream);
assertThat(new String(byteArrayOutputStream.toByteArray()), is(responseData));
}
}
How do I mock
.bean(DataService.class, "processData")
in the unit test to return a mock Data Object with its default String variable as say "Unit test success" and then test to see if the route would give back the mocked Object instead of the Object with "Hello World" String variable?
This may seem's a late response, but I faced the same thing as described in your case, and I come across a simple way to "mock" the bean step, by using the DefaultRegistry to register the mocked bean into Camel registry, for example :
#Test
public void shouldProcessData() throws Exception {
...
...
DataService dataService = new DataService(...);
stubBean("dataService", dataService); // put this before calling context.start();
context.start();
...
...
}
/**
* This method inject a stub bean into the registry
* #param beanName the name of the bean being injected
* #param instance the stub instance
*/
void stubBean(String beanName, Object instance) {
DefaultRegistry registry = context.getRegistry(DefaultRegistry.class);
registry.bind(beanName, instance);
}
You can autowired the DataService in your DataRoute like
#Component
public class DataRoute extends RouteBuilder {
#Autowired
private DataService dataService;
#Override
public void configure() throws Exception {
from("direct:getData")
.routeId("getData")
.bean(dataService, "processData")
.marshal().json(JsonLibrary.Jackson)
.end();
}
}
So you can mock the DataService as usual.
An alternative is using beanRef("beanName", "methodName") in the Route.
My client wants to have 100% code coverage for all the projects. I have written few test cases very long back for Web API's using nUnit. But my client decided to use xUnit as a unit test framework using Moq as Mock framework.
As i have never worked on unit test case for sitecore project, could anyone please en-light us on the approach? As a start coudl anyone please write a sample test case for the below method? We are using GlassMapperFramework as a ORM.
public class RegistrationController : GlassController
{
public ActionResult RegistrationInitiation()
{
var someobject = GetDataSourceItem<IRegistrationMainContent>();
return View(someobject);
}
}
To test your Controllers, you will want to inject the Sitecore Context into the Controller. The GlassController has an overload method on it GlassController(ISitecoreContext). This is used to Unit Test your controllers. It also has other overloads if needed...
Here is more complete code you need to unit test the controller
private Mock<IRegistrationModel> RegistrationModel { get; set; };
private RegistrationController Controller { get; set; }
[TestInitialize]
public void Setup()
{
var mockSitecoreContext = new Mock<ISitecoreContext>();
this.RegistrationModel = new Mock<IRegistrationModel>();
this.RegistrationModel.SetupAllProperties();
mockSitecoreContext.Setup(sc =>sc.GetItem<IRegistrationModel
(It.IsAny<string>(), false, false)).
Returns(this.RegistrationModel.Object);
this.Controller = new RegistrationController {SitecoreContext =
mockSitecoreContext.Object }
}
[TestMethod]
public void Your_Unit_Test_Name()
{
//....perform unit test here
this.Controller.SitecoreContext = null;
var result = this.Controller.GetIndex() as ViewResult;
//Assert ....
}
Let me know if you have questions!
This question already has answers here:
Injecting Mockito mocks into a Spring bean
(23 answers)
Closed 7 years ago.
I'm trying to test some controller with method-level spring security and I want to mock out the repository dependencies in the controller. Basically I want to test that (a) the methods are enforcing security and (b) other beans invoked in SpEL expressions are working.
My issue is that when using Mockito's #InjectMocks for instantiating the controller the spring security proxies are not being applied to the controller and the method security is bypassed. If I use #Autowired to allow Spring to create the controller, my custom method level security logic does get called but the #Mock objects are not injected.
#RestController
#RequestMapping("/api/projects/{projectId}")
public class ProjectKeywordResource {
//I want to mock this repository
#Inject
private ProjectKeywordRepository projectKeywordRepository;
//Invokes another bean if user not assigned admin role.
#PreAuthorize("hasRole('ROLE_ADMIN')" + " or "
+ "#projectService.canEditProjectData(#projectId)")
#RequestMapping(value = "/projectKeywords", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<ProjectKeyword> create(
#PathVariable String projectId,
#RequestBody ProjectKeyword projectKeyword)
throws URISyntaxException {
projectKeywordRepository.save(projectKeyword);
return ResponseEntity.created(
new URI("/api/" + projectId + "projectKeywords/"
+ projectKeyword.getId())).body(result);
}
}
My Test Case is here:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class ProjectKeywordResourceSecurityTest {
private static final String DEFAULT_PROJECT_ID = "1";
#Mock
private ProjectKeywordRepository projectKeywordRepository;
//#Inject - Adding the following annotation adds the necessary spring security proxies,
but then ProjectKeywordResource uses the real ProjectKeywordRepository not the mock one.
#InjectMocks
private ProjectKeywordResource projectKeywordResource;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test(expected = AccessDeniedException.class)
#WithMockUser
#Transactional
public void testCreateThrowsAccessDenied() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
#Test
#WithMockUser(username = "admin", roles={"ADMIN"})
#Transactional
public void testCreateAuthorizationSuceedsForAdminUser() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
}
Is there a bit of config magic that allows me to wrap the Mockito mock controller with the necessary spring proxies, or alternatively force the use of the Mock on the injected bean in my test case?
The link that Bewusstsein posted got me on the right track to a viable answer posted by jfcorugedo. Basically what I had to do was to create a new bean in my test configuration class that mocks the Repository class and annotate it with the #Primary annotation. Adding the Spring profile annotation allows these beans to be switched off by default and therefore doesn't interfere with other tests. The revised test class is:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#ActiveProfiles({"useMockRepositories","default"})
public class ProjectKeywordResourceSecurityTest {
private static final String DEFAULT_PROJECT_ID = "1";
#Inject
private ProjectKeywordResource projectKeywordResource;
#Test(expected = AccessDeniedException.class)
#WithMockUser
public void testCreateThrowsAccessDenied() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
#Test
#WithMockUser(username = "admin", roles={"ADMIN"})
public void testCreateAuthorizationSuceedsForAdminUser() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
My Test Configuration class has the following:
#Configuration
public class TestConfiguration {
#Profile("useMockRepositories")
#Bean
#Primary
public ProjectKeywordRepository MockProjectKeywordRepository() {
return Mockito.mock(ProjectKeywordRepository.class);
}
}
I'm trying to test my Session Beans with JUnit, but I can't. I've tried a lot of method, but still get some exceptions.
Here is what I need:
I have a few Stateless Session Beans I need to test. Each has the same #PersistenceContext and uses an EntityManager
With my test cases I need to test their methods. For instance: if I add an user with username X and then I try to add another one with the same username, I want to catch an Exception.
Can someone provide a simple and short generic test example? I've already read many, but I always get an error (I get NullPointerException for the EntityManager when I call a method like: sessionBean.method() (which does, for instance, entityManager.find(...)), or I am not able to initialize the Context, or other PersistenceException).
You might be interested in one of the latest posts of Antonio Goncalves:
WYTIWYR : What You Test Is What You Run
It tells about testing EJB with EntityManager using:
Mockito,
Embedded EJB Container,
Arquillian.
I solved creating a Stateless Session Bean and injecting its Entity Manager to test classes. I post the code in case someone will need it:
#Stateless(name = "TestProxy")
#Remote({TestProxyRemote.class})
public class TestProxy implements TestProxyRemote {
#PersistenceContext(unitName = "mph")
private EntityManager em;
#Override
public void persist(Object o) {
em.persist(o);
}
#Override
public void clear() {
em.clear();
}
#Override
public void merge(Object o) {
em.merge(o);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Object find(Class classe, String key) {
return em.find(classe, key);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Object find(Class classe, long key) {
return em.find(classe, key);
}
#SuppressWarnings("rawtypes")
#Override
public List getEntityList(String query) {
Query q = em.createQuery(query);
return q.getResultList();
}
}
public class MyTest {
#BeforeClass
public static void setUpBeforeClass() throws NamingException {
Properties env = new Properties();
env.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
env.setProperty(Context.PROVIDER_URL, "localhost:1099");
env.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
jndiContext = new InitialContext(env);
try {
proxy = (TestProxyRemote) jndiContext.lookup("TestProxy/remote");
} catch (NamingException e) {
e.printStackTrace();
}
}
}
Then I can use proxy.find() to get the entities I need, o proxy.getEntityList() to execute a query to retrieve all the instance of an Entity. Or I can add other methods if I want.
Unitils provides a really cool support for JPA. Unitils can be used with JUnit or TestNG and in case you need a mocking framework, Unitils provides its own mocking module as well as support for EasyMock.
#JpaEntityManagerFactory(persistenceUnit = "testPersistenceUnit")
#DataSet(loadStrategy = RefreshLoadStrategy.class)
public class TimeTrackerTest extends UnitilsTestNG {
#TestedObject
private TimeTrackerBean cut = new TimeTrackerBean();
#InjectInto(target="cut",property="em")
#PersistenceContext
private EntityManager em;
#Test
#DataSet("TimeTrackerTest.testAddTimeSlot.xml")
public void yourTest() {
...
}
}
#JpaEntityManagerFactory - Used to specify your persistence unit. It automatically picks up the persistence.xml from your project classpath.
#DataSet - Just in case you need to load any test data you can use this.
#TestedObject - Marks your Class Under Test
#PersistenceContext - Automatically creates your EntityManager instance from the configurations made in the persistence.xml - PersistenceUnit.
#InjectInto - Injects the em instance into the target (cut)
For more information refer this.
Hope this helps.
I'm using Needle for this. It works well with Mockito and EasyMock if you want to mock other objects.
First I write a persistencte.xml for tests (src/test/resources/META-INF) like this:
<persistence-unit name="rapPersistenceTest" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:~/test"/>
...
</properties>
</persistence-unit>
In my Junit-Testclass I write:
public class DaoNeedleTest {
//here Needle will create persistenceContext for your testclass
public static DatabaseRule databaseRule = new DatabaseRule("rapPersistenceTest");
//here you can get the entityManager to manipulate data directly
private final EntityManager entityManager = databaseRule.getEntityManager();
#Rule
public NeedleRule needleRule = new NeedleRule(databaseRule);
//here you can instantiate your daoService
#ObjectUnderTest
DAOService daoService;
#Test
public void test() {
//if your method needs a transaction here you can get it
entityManager.getTransaction().begin();
daoService.yourMethod();
entityManager.getTransaction().commit();
}
You also need a Needle-configuration File in src/test/resources, where you tell what kind of Mock-provider you are using. E.g. I'm using Mockito:
mock.provider=de.akquinet.jbosscc.needle.mock.MockitoProvider
That's it.