The error was on integration test of a service. Yes, we're currently doing integration test on our service as a workaround since we cannot test the services via unit test due to userType mapping.
Regarding userType: Our Domain uses interface as properties. In addition findByinterface won't work on grails.
see below:
class Domain {
SomeProperty someProperty
String otherProperty
}
public interface SomeProperty {
//methods
}
enum Enum implements SomeProperty {
NAME,
OTHERNAME
//implementation of methods
}
class Domain can handle different kinds of enum implementing the SomeProperty inteface.
Database won't know what particular value should it saved so we go with the userType. below is the Domain with the mapping
class Domain {
SomeProperty someProperty
String otherProperty
}
static mapping = {
id generator: 'sequence', column: 'id', params: [sequence: 'domain_sequence']
someProperty type : userType, {
column name: "someProperty", sqlType: "varchar", length: 255
}
}
Updated:
Code being tested:
class ServiceBeingTested {
AnotherServiceInsideServiceBeingTested anotherServiceInsideServiceBeingTested //or def anotherServiceInsideServiceBeingTested
public void methodBeingTested(param1, param2, param3) {
Object object = privateMethod(..., ...) //private method contains no other service calls. just pure logic
anotherServiceInsideServiceBeingTested.voidMethod1(....)
anotherServiceInsideServiceBeingTested.voidMethod2(....)
}
}
My integration test:
class ServiceBeingTestedIntegrationSpec extends IntegrationSpec {
ServiceBeingTested serviceBeingTested = new ServiceBeingTested()
AnotherServiceInsideServiceBeingTested anotherServiceInsideServiceBeingTested
void setUp () {
anotherServiceInsideServiceBeingTested = Mock()
serviceBeingTested.anotherServiceInsideServiceBeingTested = anotherServiceInsideServiceBeingTested
}
void cleanup () {
//code here
}
void "methodBeingTested should invoke the 2 service method call"() {
given:
//initialize data here
//code
when:
serviceBeingTested.methodBeingTested(param1, param2, param3)
then:
1 * anotherServiceInsideServiceBeingTested.voidMethod1(....)
1 * anotherServiceInsideServiceBeingTested.voidMethod2(....)
}
}
StackTrace:
| Too few invocations for:
1 * anotherServiceInsideServiceBeingTested.voidMethod2(....) (0 invocations)
Unmatched invocations (ordered by similarity):
1 * anotherServiceInsideServiceBeingTested.this$3$voidMethod2(....)
The other service call with same anotherServiceInsideServiceBeingTested -i.e anotherServiceInsideServiceBeingTested.voidMethod1 was correctly invoked. I tried changing the parameters in test for voidMethod2 to wildcards but will still result to this error.
Thanks
In integration test cases, you don't need to mock any of the services as these are available by default as the full application is loaded.
Though, in unit test, you may use #TestFor annotation and specify the service which you want to test, this will inject a service variable which would be available through you specification / test class.
#TestFor(Service)
class ServiceBeingTestedIntegrationSpec extends Specification {
ServiceBeingTested serviceBeingTested = new ServiceBeingTested()
void setUp () {
serviceBeingTested.service = service
}
void cleanup () {
//code here
}
void "methodBeingTested should invoke the 2 service method call"() {
given:
//initialize data here
//code
when:
serviceBeingTested.methodBeingTested(param1, param2, param3)
then:
1 * service.voidMethod1(....)
1 * service.voidMethod2(....)
}
}
Also, in case above you could also try to stub your methods in setup after mocking these to avoid any other service called by your service which will throw NullPointerException and eventually your test would fail in case of unit tests.
example of stubbing could be:
1*service.voidMethod1 >> {
//some code setting up any data for you.
}
1*service.voidMethod2 >> {
//some code setting up any data for you.
}
If you use stubbing like above you can simply write down unit test cases as well.
Related
I have a very simple class as shown
class MyClass {
public static String getName(String input)
{
return toUpperCase(input);
}
public static String toUpperCase(String name)
{
return name.toUpperCase();
}
}
To test the above I have written a Test Case using Spock FW as shown below:
class MyClassTest extends Specification{
def 'check uppercase scnario'() {
given:
MyClass myClass = new MyClass();
when:
myClass.getName("test")
then: ""
1*myClass.toUpperCase("test");
}
}
But when I run this I see 0 Interactions
You cannot verify interactions on static Java methods. Just make your methods non-static. Besides, in the given: block, you are instantiating the class, so I guess you want to use instance methods anyway.
class MyClass {
public String getName(String input) {
return toUpperCase(input);
}
public String toUpperCase(String name) {
return name.toUpperCase();
}
}
Furthermore, if you wish to verify interactions on self-invocation calls, a Mock() is not what you need. Instead, simply use a Spy():
class MyClassTest extends Specification {
def 'check uppercase scnario'() {
given:
MyClass myClass = Spy()
when:
myClass.getName("test")
then:
1 * myClass.toUpperCase("test");
}
}
Try it in the Groovy Web Console.
Using Grails 3.2.8 and the Spock framework for testing, given the following controller class:
class SomeController {
def doSomething() {
// do a few things, then:
someOtherMethod()
}
protected void someOtherMethod() {
// do something here, but I don't care
}
}
How can I test the doSomething() method to make sure someOtherMethod() is called exactly once?
This is my attempt that failed:
#TestFor(SomeController)
class SomeControllerSpec extends Specification {
void "Test that someOtherMethod() is called once inside doSomething()"() {
when:
controller.doSomething()
then:
1 * controller.someOtherMethod(_)
}
}
Error message:
Too few invocations for:
1 * controller.someOtherMethod(_) (0 invocations)
Note: Imports have been omitted to focus on the problem at hand
You can't do that as controller is not a mocked object. Instead, you need to use metaclass like this:
#TestFor(SomeController)
class SomeControllerSpec extends Specification {
void "Test that someOtherMethod() is called once inside doSomething()"() {
given:
Integer callsToSomeOtherMethod = 0
controller.metaClass.someOtherMethod = {
callsToSomeOtherMethod++
}
when:
controller.doSomething()
then:
callsToSomeOtherMethod == 1
}
}
For an Azure Service Fabric stateful service it is possible to inject the IReliableStateManager as follows:
ServiceRuntime.RegisterServiceAsync("MyServiceType", context =>
{
IReliableStateManager stateManager = new ReliableStateManager(context);
return new MyService(stateManager);
}
And this way you can mock IStateManager in unit tests for MyService.
The same doesn't seem possible for a stateful actor. IActorStateManager only has an internal implementation: Microsoft.ServiceFabric.Actors.Runtime.ActorStateManager. So how do I unit test a stateful actor?
At some point in my actor methods a call is made to IActorStateManager but since I can't inject this dependency, unit tests seem impossible.
Is there some way to work around this or is there another solution?
No, IActorStateManager isn't injectable today, but we're working on making it so. For now (without using reflection) you'll have to wrap your state operations in something that you can inject, and have that call into the state manager, which you can then mock for unit testing.
I usually write actor business logic in separate class that have constructor with IStateManager parameter and implement my actor interface. Actor is just wrapper around actor implementation class and I test actorImpl class instead of actor. Look at the code:
public interface IMyActor01 : IActor
{
Task<int> GetCountAsync();
Task SetCountAsync(int count);
}
public class MyActor01Impl : IMyActor01
{
private readonly IActorStateManager StateManager;
public MyActor01Impl(IActorStateManager stateManager)
{
this.StateManager = stateManager;
this.StateManager.TryAddStateAsync("count", 0);
}
public Task<int> GetCountAsync()
{
return this.StateManager.GetStateAsync<int>("count");
}
public Task SetCountAsync(int count)
{
return this.StateManager.AddOrUpdateStateAsync("count", count, (key, value) => count > value ? count : value);
}
}
[StatePersistence(StatePersistence.Persisted)]
internal class MyActor01 : Actor, IMyActor01
{
private MyActor01Impl Impl;
protected override Task OnActivateAsync()
{
ActorEventSource.Current.ActorMessage(this, "Actor activated.");
this.Impl = new MyActor01Impl(this.StateManager);
return Task.FromResult(true);
}
Task<int> IMyActor01.GetCountAsync()
{
return this.Impl.GetCountAsync();
}
Task IMyActor01.SetCountAsync(int count)
{
return this.Impl.SetCountAsync(count);
}
}
[TestFixture]
public class TestFixture01
{
[Test]
public void Test01()
{
//ARRANGE
var dictionary = new Dictionary<string, object>();
var impl = new MyActor01Impl(new StubStateManager(dictionary));
//ACT
impl.SetCountAsync(12).Wait();
//ASSERT
Assert.AreEquals(12, impl.GetCountAsync().Result);
//or
Assert.AreEquals(12, (int)dictionary["count"]);
}
}
I can share StubStateManager implementation if you want.
I'm trying to establish a way of unit testing my service layer (& repositories) using some dummy data. I've seen examples of this before with Generic Repositories but I'm struggling to get something working whilst using a DatabaseFactory.
When I call the GetPhrase method from repository.Object I just get null back everytime.
I'm using NUnit and Moq. Any pointers on where i'm going wrong would be appreciated, or let me know if i'm better off going down a different road
e.g. Connecting to a local db for tests (SQL CE etc)
Here are the main components of the code:
public class PhraseRepository : RepositoryBase<Phrase>, IPhraseRepository
{
public PhraseRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
}
public string GetPhrase(string phraseCode)
{
return this.GetMany(p => p.PhraseCode == phraseCode).First().Descript;
}
}
public interface IPhraseRepository : IRepository<Phrase>
{
string GetPhrase(string phraseCode);
}
public class CLPRiskPhraseService : ICLPRiskPhraseService
{
private readonly IPhraseRepository phraseRepository;
public string GetPhrase(string phraseCode)
{
return phraseRepository.GetPhrase(phraseCode);
}
}
[Test]
public void GetPhrase()
{
var phrases = new FakePhraseData().GetPhrases();
phraseRepository.Setup(m => m.GetMany(It.IsAny<Expression<Func<Phrase, bool>>>())).Returns(phrases);
var result = phraseRepository.Object.GetPhrase("H300");
// Assert
NUnit.Framework.Assert.IsNotNull(phraseRepository.Object);
NUnit.Framework.Assert.AreEqual("Description0", result);
}
Invoking phraseRepository.Object.GetPhrase("H300") in your test will always return null unless you set it up to return something different.
I think you're mistakenly thinking that this call to GetPhrase will invoke GetMany like the concrete PhraseRepository does, but you need to remember that it's just a mock of the interface IPhraseRepository. A method on a mocked object will always return the default value of the return type (in this case string) unless you use Setup to change the behavior of that method.
I have a few tests that are very similar in my Grails integration test suite (which uses Spock). I want to have a base test class which has the 90% of the common logic of the tests and then let test classes extend from it.
I was thinking:
public abstract BaseSpecification extends IntegrationSpec {
public baseTest() {
//
setUp:
//
...
when:
//
...
then:
...
}
}
and then:
public class SpecificTestSpecification extends BaseSpecification {
public baseTest() {
setup:
// more set up
super.baseTest();
when:
// some more specific testing
then:
// som more testing
}
}
But trying this I get two issues:
It runs both BaseClass and SpecificationClass
When the SpecificationClass runs, it fails on:
groovy.lang.MissingMethodException: No signature of method: BaseSpecification.baseTest() is applicable for argument types: () values: []
Possible solutions: any(), old(java.lang.Object), any(groovy.lang.Closure), notify(), wait(), Spy()
at
Any ideas how I can achieve inheritance in my spock integration tests?
I don't know if it can be done with Spock. When I tried I couln't find a way to reuse spock statements and what I did was to write a BaseSpecification class with utility methods that can be used inside spock statements.
This is an example test.
#TestFor(Address)
class AddressSpec extends BaseSpecification {
...
void "Country code should be 3 chars length"(){
when:
domain.countryCode = countryCode
then:
validateField('countryCode', isValid, 'minSize.notmet')
where:
[countryCode, isValid] << getMinSizeParams(3)
}
And the BaseSpecification class
class BaseSpecification extends Specification {
// Return params that can be asigned in `where` statement
def getMinSizeParams(Integer size){[
[RandomStringUtils.randomAlphabetic(size - 1), false],
[RandomStringUtils.randomAlphabetic(size), true]
]}
// Make an assetion, so it can be used inside `then` statement
protected void validateField(String field, String code, Boolean shouldBeValid){
domain.validate([field])
if(shouldBeValid)
assert domain.errors[field]?.code != code
else
assert domain.errors[field]?.code == code
}
}
It's an unit test but I think it should work with Integration tests too.
Okay, now I got your point.
You can pretty much use like this:
class BaseSpecification extends IntegrationSpec {
//User userInstance
def setup() {
// do your common stuff here like initialize a common user which is used everywhere
}
def cleanup() {
}
}
class SpecificTestSpecification extends BaseSpecification {
def setup() {
// specific setup here. Will call the super setup automatically
}
def cleanup() {
}
void "test something now"() {
// You can use that userInstance from super class here if defined.
}
}