chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Hi,
we use a following model to implement singletons. I'd like to know how a test would look like that tests that when the Singleton is created, it creates the two members and also a test for each of the methods (MethodA and MethodB). I do not want to have class MemberA and class MemberB part of the test. I only want to make sure that the specified methods are called from the Singleton to the members. Is this possible with TypeMock. If not, what do I need to change to make it doable?
Thanks
Step


namespace SingletonExample
{
public class MemberB
{
public void DoSth(){}
public void DoSthMore(){}
}

public class MemberA
{
public void DoSthElse() {}
public void DoSthCompleteDifferent(){}
}

public class SampleSingleton
{
private readonly static SampleSingleton _instance = Create();
private MemberB memberB;
private MemberA memberA;

private static SampleSingleton Create()
{
SampleSingleton instance = new SampleSingleton();
instance.memberA = new MemberA();
instance.memberB = new MemberB();

return instance;
}

public SampleSingleton Instance
{
get { return _instance; }
}

public void MethodA()
{
memberB.DoSth();
memberA.DoSthElse();
}

public void MethodB()
{
memberB.DoSthMore();
memberA.DoSthCompleteDifferent();
}
}


}
asked by Step (3.4k points)

7 Answers

0 votes
Hi
What you need here is to mock MemberA and MemberB
Here is how you do it using natural mocks:
[Test]
public void Test()
{
   using(RecordExpectations record = RecorderManager.StartRecording())
   {      
      MemberA mockMemberA = new MemberA();
      MemberB mockMemberB = new MemberB();

      mockMemberA.DoSthElse();
      mockMemberA.DoSthCompleteDifferent();

      mockMemberB.DoSth();
      mockMemberB.DoSthMore();
   }
   
   // Call the code you need to test here ... 
   
   MockManager.Verify();
}


MockManager.Verify() will make sure that all the expected methods in the recording block are called.

Hope it helps.
answered by ohad (35.4k points)
0 votes
Hi ohad,
thanks for the reply. I tried this but I encountered the following issues.
Since SampleSingleton is a singleton, the only instance is initialized when the class is created the first time through the static method Create(). This happens only once. If I have more then one test, the Create will be called only for the first test. Since with NUnit I do not know which is the first test that gets executed, I do not really know when the static Create is called. I also think that the test should have allways the same results, regardless in which order they are executed.
So how can I mock the calls inside Create if create was called without having the same code in each test method?
How can I make the test independent of the execution order?
Is there a better pattern for a singleton that supports unit testing better?
-Step
answered by Step (3.4k points)
0 votes
Hi
All you need to do is move the mocking code to a setup method
and add record.DefaultBehavior.RepeatAlways()
so it looks like this:
        [SetUp]
        public void Setup()
        {
            using (RecordExpectations record = RecorderManager.StartRecording())
            {
                record.DefaultBehavior.RepeatAlways();
                MemberA mockMemberA = new MemberA();
                MemberB mockMemberB = new MemberB();

                mockMemberA.DoSthElse();
                mockMemberA.DoSthCompleteDifferent();

                mockMemberB.DoSth();
                mockMemberB.DoSthMore();
            }            
        }


Hope it solves the problem :)
answered by ohad (35.4k points)
0 votes
Thanks for your reply.

It helps me only a little bit.

This should be part of the Test for methodA
mockMemberA.DoSthElse();
mockMemberA.DoSthCompleteDifferent();

and this should be part of methodB
mockMemberB.DoSth();
mockMemberB.DoSthMore();

It should not be part of the setup, right? I also want to have the tests very strict, CheckArguments() and AllMethods to make sure the code is only doing what is is supposed to do.

I tried following code, but it still did not do what I wanted. The MockManager.Verify in the Setup method screws up both tests. It seems like that the recorder does not Mock the calls in the test methods anymore.
There must be an easier way, no?

[TestFixture]
public class TEstSampleSingleton
{
private MemberA mockMemberA;
private MemberB mockMemberB;

[SetUp]
public void Setup()
{
using (RecordExpectations record = RecorderManager.StartRecording())
{
record.DefaultBehavior.RepeatAlways();
record.DefaultBehavior.CheckArguments();
record.DefaultBehavior.Strict = StrictFlags.AllMethods;

mockMemberA = new MemberA();
mockMemberB = new MemberB();
}

MockManager.Verify();
}

[Test]
public void MethodA_Test()
{
using (RecordExpectations record = RecorderManager.StartRecording())
{
record.DefaultBehavior.CheckArguments();
record.DefaultBehavior.Strict = StrictFlags.AllMethods;
mockMemberB.DoSth();
mockMemberA.DoSthElse();
}

SampleSingleton.Instance.MethodA();
MockManager.Verify();
}

[Test]
public void MethodB_Test()
{

using (RecordExpectations record = RecorderManager.StartRecording())
{
record.DefaultBehavior.CheckArguments();
record.DefaultBehavior.Strict = StrictFlags.AllMethods;
mockMemberB.DoSthMore();
mockMemberA.DoSthCompleteDifferent();
}

SampleSingleton.Instance.MethodB();
MockManager.Verify();
}

}
answered by Step (3.4k points)
0 votes
Hi
The problem is the call to MockManager.Verify in the Setup method.
When you do that it clears the mocks you set in the setup before the test methods started to run.

Try this:
[SetUp]
public void Setup()
{
   using (RecordExpectations record = RecorderManager.StartRecording())
   {
      record.DefaultBehavior.RepeatAlways();
      record.DefaultBehavior.CheckArguments();
      record.DefaultBehavior.Strict = StrictFlags.AllMethods;

      mockMemberA = new MemberA();
      mockMemberB = new MemberB();
   }
   //MockManager.Verify();
}


:idea: In some cases you might find it useful to use:
record.VerifyMode = VerifyMode.DontClear;
answered by ohad (35.4k points)
0 votes
Thanks ohad,
your tips about putting repeating mocking code into the setup method where helpfull.

I think the best is to test the object as a non-singleton. Otherwise I introduce a state into my tests that is kept acrosss multiple tests (which I think is bad)
answered by Step (3.4k points)
0 votes
On behalf of Ohad :)
"thank you. Glad I could help."

In any case, trying to avoid mocking of static methods is a good strategy. In most cases when tests start to interfere with one another it involves static mocking.
answered by lior (13.2k points)
...