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
Hello,

I'm trying to test if a method on a service proxy is called. Apparently I'm missing something, and I need some help to get this working.

This is the code I wish to test (very simple and stripped down!):

        public void CreateDebtor(AxdEntity_CustTable debtor)
        {
            HndDebtorsService service;
            string username = Thread.CurrentPrincipal.Identity.Name;

            WcfService custService = new WcfService("WSHttpBinding_HndDebtorsService", typeof (HndDebtorsServiceChannel), null);
            OperationContextScope oScope = new OperationContextScope((IClientChannel) custService.Channel);
            using (oScope)
            {
                AuthenticationHelper.SetHeader(username);

                service = factory.CreateInstance<HndDebtorsService>(custService);

                debtor.@class = "entity";

                HndDebtorsServiceCreateRequest customerServiceCreateRequest = new HndDebtorsServiceCreateRequest();

                AxdHndDebtors debtors = new AxdHndDebtors {CustTable = new AxdEntity_CustTable[1]};
                debtors.CustTable[0] = debtor;
                customerServiceCreateRequest.HndDebtors = debtors;

                Logger.Instance.Log("About to save customer", LoggerEnums.Severity.DEBUG, debtor);

                // I want to verify that service.create is called!
                HndDebtorsServiceCreateResponse response = service.create(customerServiceCreateRequest);

                Logger.Instance.Log("Customer saved, response:", LoggerEnums.Severity.DEBUG, response.EntityKeyList);
            }
        }


HndDebtorsService is an interface, it's just the naming which is horrible.

So, my initial thoughts in verifying that service.create is called was something like this:

        [Test, Isolated]
        public void CreateDebtor_CreatingDebtor_CreateIsCalled()
        {
            // ARRANGE
            RS_DebtorService service = new RS_DebtorService();
            HndDebtorsService fakeService = Isolate.Fake.Instance<HndDebtorsService>();
            Isolate.Swap.NextInstance<HndDebtorsService>().With(fakeService);

            Isolate.WhenCalled(() => fakeService.create(null)).WillReturn(null);

            // ACT
            service.CreateDebtor(null);

            // ASSERT
            Isolate.Verify.WasCalledWithAnyArguments(() => fakeService.create(null));
        }


Unfortunately this doesn't work since I'm not able to fake an interface.

So, next try was to create a fake implementation of the interface, and swap the next instance of the interface with the fake implementation. Unfortunately I'm getting an error saying "Item has already been added. Key in dictionary: 'dm' Key being added: 'dm'"

So, any suggestions?
asked by Jan-Erik (1.4k points)

8 Answers

0 votes
Hi Jan-Erik,

If I'm reading the code under test properly, the interface is returned by the factory method factory.CreateInstance(). Can you try to use the following instead of Swap.NextInstance?
Isolate.WhenCalled(() => factory.CreateInstance<HndDebtorsService>(null).WillReturn(fakeService);


This way the fake service is inserted to the code under test at the point where the factory method is supposed to return the concrete instance. Note you cannot use the future instance pattern (Swap.NextInstance.With()) with an interface, as this pattern is triggered on the next 'new' statement, which is of course invalid for interfaces.

Please let me know if this helps.
Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Hi,

Thanks for your quick reply. This seems logical, but it didn't work. I get this error: Operation is not valid due to the current state of the object.

It's failing on Isolate.WhenCalled...

            HndDebtorsServiceClient fakeService = Isolate.Fake.Instance<HndDebtorsServiceClient>();
            Isolate.WhenCalled(() => factory.CreateInstance<HndDebtorsService>("")).WillReturn(fakeService);


Just for debugging I tried to call factory.CreateInstance, and that didn't fail. So it fails only when inside Isolate.WhenCalled.
answered by Jan-Erik (1.4k points)
0 votes
Jan-Erik,

This is pretty strange indeed, let's take this offline. I will send you an email from our support mailbox to follow up on this.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Jan-Erik,

This is pretty strange indeed, let's take this offline. I will send you an email from our support mailbox to follow up on this.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
So was this resolved? Can you guys put the solution here? I'm running the same error with the following code:

SqlConnection fakeSC = Isolate.Fake.Instance<SqlConnection>(Members.ReturnNulls, ConstructorWillBe.Ignored);
Isolate.Swap.NextInstance<SqlConnection>().With(fakeSC);
Isolate.WhenCalled(() => fakeSC.Open()).IgnoreCall(); // exception occurs on this line
saoTarget.AuditEvent(adNonOrder); // this is code to be tested
Isolate.Verify.WasCalledWithAnyArguments(() => fakeSC.Open());

I got the same exception (Operation is not valid due to the current state of the object.) at the IsoLate.WhenCalled line.

When I looked the call stack it looks like this:
at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at Eclipsys.SunriseXA.MM.UnitTest.Framework.SqlAuditTargeted_Cases.<>c__DisplayClass2.<TestAuditEvent>b__0()

So the SqlConnection object is not faked at all? Why is the real object called here?

Thanks for any help.
answered by rzhu (2.8k points)
0 votes
I'm not sure because the code is missing the definition of saoTraget but I think you're missing an important call that tells isolator to replace the next created SqlConnection with the fake instance (fakeSC):
Isolate.Swap.NextInstance<SqlConnection>().With(fakeSC);


I need the code that defines (and initialize) saoTraget so I can investigate this issue.


Dror Helper
Typemock Support
answered by dhelper (11.9k points)
0 votes
Actually saoTarget is not the object to be faked. Here's more of the code:

                
SqlAuditTargeted saoTarget = new SqlAuditTargeted(testObjName, testProcName);

SqlConnection fakeSC = Isolate.Fake.Instance<SqlConnection>(Members.ReturnNulls, ConstructorWillBe.Ignored);
Isolate.Swap.NextInstance<SqlConnection>().With(fakeSC);
Isolate.WhenCalled(() => fakeSC.Open()).IgnoreCall();

saoTarget.AuditEvent(adNonOrder);
Isolate.Verify.WasCalledWithAnyArguments(() => fakeSC.Open());



a new SqlConnection object is created inside the AuditEvent() function of saoTarget, like this:

      
public void AuditEvent(AuditData data)
{
    // log order modification
    using ( SqlConnection cn = new SqlConnection(data.ConnectString) )
    {
        cn.Open();
        ...


I thought that the "new SqlConnection" statement in AuditEvent() should be faked, so that the "cn.Open()" should not be passed through to an original object. But the call stack seems to suggest that the Open() call was invoked on a real SqlConnection object.

at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()

Thanks in advance for any suggestions


Richard Zhu
answered by rzhu (2.8k points)
0 votes
First of all you're correct - the new SqlConnection statement should be faked.
I'm having difficulties reproducing the problem, I'll need an example project that shows this issue - let's investigate this issue offline .
answered by dhelper (11.9k points)
...