Does anyone know how to run unit tests for Liferay portlets? I have found a lot of posts about it (e.g. http://agile-reflections.opnworks.com/2010/06/portlet-unit-testing-with-liferay-6.html) but none works nonetheless.
This may be overkill, but if you're looking for an Enterprise approach with continuous integration testing, this blog gives a very good example: Continuous integration on Liferay: running your Selenium 2 tests on the Tomcat 6 bundle
Unit testing Liferay portlets is quite complicated when ServiceBuilder is utilized.
The reason is that it generates quite heavy services that contain references not only to beans within Portlet, but even to the Portal beans generated by ServiceBuilder.
There are tools like InitUtil.init(); that lets you at least instantiate and use ServiceBuilder entities... not EntityServices though. For that you'd have to use SpringUtil.loadContext(); that requires
System.setProperty("external-properties", "testing.properties");
where testing.properties contains :
spring.configs=META-INF/ext-spring.xml,\
META-INF/base-spring.xml,\
META-INF/dynamic-data-source-spring.xml,\
META-INF/infrastructure-spring.xml,\
META-INF/shard-data-source-spring.xml,\
META-INF/hibernate-spring.xml,\
META-INF/portlet-spring.xml
These are spring definitions to be loaded for testing application context. It all would be OK, but beans from portlet-spring.xml are those heavy services containing references to Portal bean definitions like ResourceService, UserLocalService, CounterLocalService and you would have to load even META-INF/portal-spring.xml and trust me, it's not that easy cause then you'd have to load quite a lot of other stuff.
THE ANSWER:
The truth is, that you most likely won't have to unit test portlet SB services, never. They represent entities with persistence and service layer around. Something that is not to be tested. You just have to mock them and stub their methods, right ?
And the best way for junit and integration testing as to mocking is not using *LocalServiceUtil static classes in your application, because it is almost unmockable.
You just need to create a Spring FactoryBean :
public class PortalFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortalBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
public class PortletFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortletBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
<bean id="somePortalBean" class="example.spring.PortalFactoryBean" lazy-init="true">
<property name="type" value="com.liferay.some.util.SomeService"/>
</bean>
<bean id="somePortletBean" class="example.spring.PortletFactoryBean" lazy-init="true">
<property name="type" value="com.example.SomeService"/>
</bean>
#Autowired
private SomeService somePortalBean;
Writing unit/integration tests for this portlet would be quite easy, right ? You just create a spring context for testing and you mock these services :
Using Service Builder is worth it, but you must have some Spring knowledge and play with it for some time. Then it spares a lot of time because it is easy to maintain.
You need to have some third party libraries on classpath.
THe key point is having even portal-impl.jar and other portal dependencies on classpath and having InitUtil.initWithSpring(boolean); load up core spring xml configs that you specify in spring-ext.properties in spring.congigs property, only those services you need. You may need no portal services and only the portlet ones, but this is a problem because your portlet services generated by service builder use the portal services.
Using service builder just needs good knowledge of spring and classloading.
But you need to understand the infrastructure before doing that. There are quite a lot of hacks needed... Like
BeanLocator beanLocator = new BeanLocatorImpl(PortalClassLoaderUtil.getClassLoader(), ac);
PortletBeanLocatorUtil.setBeanLocator("portlet", beanLocator);
Related
i am using spring cloud's eureka and feign to communicate between some services (lets say A and B). Now id like to unittest my service layer of a single service (A). The problem is, that this service (A) is using a feign client to request some information of the other service (B).
Running the unittests without any special configuration throws the following exception: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-b => but i do not want any server to run.
My question is: Is there a way to mock the feign client, so i can unittest my service (A) without running an eureka instance and service (B)?
Edit:
I ended up creating a stub for the feign client. The stub is marked as a primary component to force spring instantiating the stub within my tests.
This is the solution i came up with.
//the feign client
#FeignClient("user")
public interface UserClient {
UserEntity getUser();
}
//the implementation i use for the tests
#Component
#Primary //mark as primary implementation
public class UserClientTestImpl implements UserClient {
#Override public UserEntity getUser() {
return someKindOfUser;
}
}
The question is ... do you even need to mock? I often see that people mention "mock" as the first solution to anything that "should not be part of the unit test". Mocking is a technique, not the solution to everything. (see here).
If you are still at the early stages of your code, just refactor and use something else instead of depending on the concrete instance of the Feign Client. You might use an interface, an abstract class, a trait or whatever you want. Don't depend on the object itself, otherwise you have to "mock it".
public interface IWebClient {
public String get(...);
public String post(...);
}
To the question: but I will have other code that will do exactly the same (except that it will be on the concrete instance of Feign), what do I do then?
Well, you can write a functional test and call an instance of a web server that you can setup locally - or use Wiremock, as mentioned by Marcin Grzejszczak in one of the answers.
public class FeignClientWrapper implements IWebClient {
private feign = something
public String get() {
feign.get( ... )
}
public String post() {
feign.post( ... )
}
}
Unit tests are used to test algorithms, if/else, loops: how units work. Don't write code to make mocks fit - it must be the other way around: your code should have less dependencies, and you should mock only when you need to verify the behavior (otherwise you can use a stub or a fake object): do you need to verify the behavior? Do you need to test that a particular method gets called in your code? Or that a particular method gets called with X, Y, and Z for 3 times in a row? Well, then yes, mocking is ok.
Otherwise, use a fake object: what you want is to test just the call/response and maybe the status code. All you probably want is to test how your code reacts to different outputs (e.g., the field "error" is present or not in a JSON response), different status codes (assuming that the Client documentation is right: 200 OK when GET, 201 when POST, etc).
Mocking a feign client is really useful in microservice component tests. You want to test one microservice without having to start all the other microservices.
If you're using Spring (and it looks like you are), the #MockBean annotation together with a bit of Mockito code will do the job.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.DEFINED_PORT)
public class TestYourComponent {
#Configuration
#Import({YourConfiguration.class})
public static class TestConfiguration {
}
#MockBean
private UserClient userClient;
#Test
public void someTest()
{
//...
mockSomeBehavior();
//...
}
private void mockSomeBehavior() {
Mockito.doReturn(someKindOfUser).when(userClient).getUser();
}
}
If you need to use a mock you can use Wiremock to stub the response for a given request - http://wiremock.org/stubbing.html. That way you will do integration tests with real HTTP requests sent. For unit testing the answer from #Markon is very good.
What is the difference between mocking service and assign instance of class to service?
For example:
class MyService {
def CallServiceMethod(){
my business logic
}
}
class MyController {
def myService
def callServiceMethod(){
myService.callServiceMethod()
}
}
#TestFor(MyController)
class MyControllerTests {
#Before
void setup() {
controller?.myService = new MyService()
vs
controller?.myService = mockFor(MyService)
}
void testCallServiceMethod(){
controller.callServiceMethod()
}
}
Any one help me please?
When using Spring, you typically lose a lot of behavior if you create a new instance of a class that's registered as a Spring bean. Beans often have multiple other beans dependency-injected into them and those fields would be null in a plain new instance, and various annotations trigger wrapping the bean instance in one or more proxies that add extra checks and behavior before and/or after your methods are called - and that won't happen with a new instance. These proxies include the transactional wrapper you get with #Transactional, the cache checks from #Cacheable, and security checks from #Secured and other Spring Security annotations.
In addition, Grails adds a lot of code to most artifacts (in particular domain classes and controllers). Most of that is added to the bytecode, but some is added at runtime to the metaclass. Although the bytecode is there for a new instance, it often needs a final bit of configuration at runtime. For example there are over 100 GORM methods added to domain classes, but they don't work by themselves and need to be "hooked up" to the current GORM implementation (Hibernate, MongoDB, etc.) This is why you sometimes see an error like "this class was used outside of a Grails application" - the class for some reason didn't have a GORM impl attached, so it can't function.
mockFor and annotations like #TestFor and #Mock don't add all of this behavior, but they do add a large subset of it, and they add mocked but realistic implementations of many methods. The goal is to give the collaborators of your class under test enough run-app-like behavior that they work essentially like they would in a real app, so you can focus on the class being tested without having to think about configuring a test database, or fake web requests and responses, etc.
I have a business rule visual studio class library (.NET 2.0) project that takes a dependency on Dynamics Crm Web Services - a classic SOAP web reference as opposed to a WCF endpoint. I want to unit test those business rules without having a real crm instance behind it. Adding a web reference doesn't produce an interface that I can fake. It does generate c# in my project that I think I can fake if I can create the interface. I don't think I need to actually navigate HTTP and get into all of the protocol stuff.
I saw Joh Skeet's blog post. Alas I didn't want to write any code and I'm hoping a tool has been written since then that might help. I tried some of his steps but concluded that he is smarter than me and I couldn't make that work.
I am aware of SoapUI, however, I was hoping for pure unit tests that would work in a CI build environment.
Is there a way to do this.
The standard way to mock something which doesn't come with an interface, is to build your own wrapper around it.
the code you want to mock, say the webservice stuff:
class AutoGeneratedStuff
{
public string GeneratedMethodYouUse()
{...}
public string GeneratedMethodYouDontNeed()
{...}
}
you then make an interface which covers only the bits of the code you need:
public interface IWebServiceClient
{
string MethodYouUse();
}
and a concrete wrapper class which implements it, which has a dependency to the generated stuff
class WebServiceClient : IWebServiceClient
{
private AutoGeneratedStuff _stuff;
public WebService(AutogeneratedStuff stuff)
{
_stuff = stuff;
}
public string MethodYouUse()
{
return _stuff.MethodYouUse();
}
}
then, in your code when you would have called the generated class, call your interface instead. In your unit tests, you can mock the interface, either using a mocking framework, or by implementing the interface with another concrete class that has no dependencies to the generated stuff
How would you go about integration testing a spring application that is annotation-configured and component-scanned and does not have an XML configuration at all? I'm hitting a wall with the need to replace production components with testing components without actually resorting to xml configuration or reflection injections to all the #autowired parts.
Example:
interface A {...}
#Component
class AImpl implements A {
...
}
interface B {...}
#Component
class BImpl implements B {
#Autowired A a;
...
}
interface C {...}
class CImpl implements C {
#Autowired B b;
...
}
then in my test I want to use ATestImpl, but I only have access to C (integration testing C).
How would you go about doing that?
Take advantage of #Primary annotation:
#Service
#Primary
public class TestA implements A {
//...
}
If there is more than one bean implementing A, Spring will prefer the one annotated with #Primary. If you place TestA class in /src/test/java, it will only be picked up during test execution, on normal context startup Spring won't see TestA and use only avaialble AImpl.
Use a dedicated spring context XML file where you override AImpl with an instance of ATestImpl. Of course, it uses XML, but I don't see any other solution (other than repackaging the application with your ATestImpl annotated class instead of the AImpl one)
The new Bean Profile features in Spring 3.1 address the need to swap injected components for testing by defining profiles e.g. test, production etc.
The link to the blog post is here. The Spring team have today released the second milestone release of Spring 3.1.
You can use a special component scan for your test, that exclude the "normal" class and add the test class.
If you have several different test classes, then they should not have a #Component Annotation (or #Service, ...). Instead they should be loaded by an XML Bean declaration. So you can have different XML files for different setups.
<context:component-scan base-package="com.queomedia.sgcrm.base">
<context:exclude-filter expression="com\.example\.AImpl" type="regex"/>
</context:component-scan>
<bean class="com.example.ATestImpl"/>
Using Spring annotation config classes, code the #Bean methods to interfaces. The prod config can perform a componentscan on the high-level package(s) to load the prod objects and the test configs can individually specify beans to return the test versions of your objects. This works very well for component testing where faking service calls and DAO objects is necessary.
I'm working on a web application that is built over Sitecore CMS. I was wondering if we could unit test for example a method that takes some data from Sitecore makes some processing with it and spits out a result. I would like to test all the logic within the method via a unit test.
I pretty confused after searching the internet wide and deep. Some say that this kind of testing is actually integration testing and not unit testing and I should test only the code that has no Sitecore calls, others say that this is not possible because the Sitecore context would be missing.
I would like to ask for your help experienced fellow programmers:
Can I unit test a method that contains Sitecore calls ? If YES, how ? If NO, why ? Is there any workaround ?
The project is at its beginning, so there will be no problem in choosing between unit testing frameworks such as MSTest or Nunit, if it is the case that the solution is related to the unit testing framework of choice.
It's pretty hard to find out anything about Sitecore without providing email and living through the sales pitch, so I'll just provide a generic approach on how to do something like this.
First and foremost, you assume that the Sitecore API is guaranteed to work - i.e. it's a framework - and you don't unit test it. You should be unit testing your interactions with it.
Then, download MOQ and read the quick start on how to use it. This is my preferred mocking framework. Feel free to use other frameworks if you wish.
Hopefully, Sitecore API provides a way for you to create data objects without dealing with persistence - i.e. to simply create a new instance of whatever it is you are interested in. Here is my imaginary API:
public class Post {
public string Body {get;set;}
public DateTime LastModified {get;set;}
public string Title {get;set;}
}
public interface ISiteCorePosts {
public IEnumerable<Post> GetPostsByUser(int userId);
}
In this case unit testing should be fairly easy. With a bit of Dependency Injection, you can inject the SiteCore interfaces into your component and then unit test it.
public class MyPostProcessor {
private readonly ISiteCorePosts m_postRepository;
public MyPostProcessor(ISiteCorePosts postRepository) {
m_postRepository = postRepository;
}
public void ProcessPosts(int userId) {
var posts = m_postRepository.GetPostsByUser(userId);
//do something with posts
}
}
public class MyPostProcessorTest {
[TestMethod]
ProcessPostsShouldCallGetPostsByUser() {
var siteCorePostsMock = new Mock<ISiteCorePosts>();
//Sets up the mock to return a list of posts when called with userId = 5
siteCorePostsMock.Setup(m=>m.GetPostsByUser(5)).Returns(new List<Post>{/*fake posts*/});
MyPostProcessor target = new MyPostProcessor(siteCorePostsMock.Object);
target.ProcessPosts(5);
//Verifies that all setups are called
siteCorePostsMock.VerifyAll();
}
}
If ISiteCorePosts is not, in fact, an interface and is a concrete class whose methods are not virtual and thus cannot be mocked, you will need to use Facade pattern to wrap the SiteCore interaction to make it more testing friendly.
public class SiteCorePostsFacade {
SiteCorePosts m_Posts = new SiteCorePosts();
//important - make this method virtual so it can be mocked without needing an interface
public virtual IEnumerable<Post> GetPostsByUser(int userId) {
return m_Posts.GetPostsByUser(userId);
}
}
You then proceed to use SiteCorePostsFacade as though it was an interface in the previous example. Good thing about MOQ is that it allows you to mock concrete classes with virtual methods, not just interfaces.
With this approach, you should be able to inject all sorts of data into your application to test all interactions with SiteCore API.
we have used a custom WebControl placed on a WebForm for our integration tests some years now, which wraps the NUnit Test Suite runner functionality much like the NUnit GUI. It show a pretty grid of executed tests with links to fixtures and categories to execute specific tests. Its created much like described here http://adeneys.wordpress.com/2010/04/13/new-technique-for-unit-testing-renderings-in-sitecore/ (the custom test runner part). Our implementation can also return raw NUnit xml for further processing by for example a build server.
I've tried MSTest a while back and it also works when specified that it should launch a WebDev / IIS site to test. It works but is extremely slow compared to above solution.
Happy testing!
Short answer:
You need to mock calls to SiteCore CMS.
Long answer:
I am not aware about SiteCore CMS. But, from your question looks like it is something that is external to your application. Components external to your system should always be used via interface. This has two benefits:
If you want to use another CMS system, you can easily do as your application is just talking to an interface.
It helps you with behavior testing by mocking the interface.
The code you write is your responsibility and hence you should only unit test that piece of code. Your unit tests should ensure that your code calls appropriate SiteCode CMS methods in various scenarios (behavior tests). You can do this using mocking. I use moq for mocking.
As tugga said, it depends upon how tightly the code you want to test is coupled to SiteCore. If it's something like:
SomeSiteCoreService siteCoreDependency = new SomeSiteCoreService()
Then this would be very difficult to test. If SiteCore provides you an interface, then you have more flexibility to unit test it. You could pass the implementation into your method either (contstructor, class property, or method parameter) and then you can send in a fake implementation of that service.
If they do not provide you with an interface, then you have to do a little more work. You would write an adapter interface of your own and the default implementation would delegate to the 3rd party dependency.
public interface ICMSAdapter{
void DoSomethingWithCMS()
}
public class SiteCoreCMSAdapter: ICMSAdapter{
SiteCoreService _cms = new SiteCoreService();
public void DoSomethingWithCMS(){
_cms.DoSomething();
}
That keeps your 3rd party dependencies at arms length and provides seams to all sorts of cool things, like unit tests and you do interception style architecture and do your own thing before and after the call.
}
I was able to get unit tests to interact with sitecore api in VS 2015. The same test throws a StackOverflow exception when run in VS 2012.
For example, this method call runs fine in VS2015 but not VS2015:
Context.SetActiveSite("mysite");
quick note: this assumes you have a site named mysite setup in your config file