Mahesh Alle
Mahesh Alle

Reputation: 329

How to mock the class object which is created inside a method using new keyword in MOQ

I am using Moq to write a unit test cases.

Code:

public class SavingAccount  
{  
    public void Data()  
    {  
        //Some logic
    }  
}  

public class Account  
{  
    public void GetAccountDetails()  
    {  
        SavingAccount savingAccount = new SavingAccount();  
        savingAccount.Data();  

        //Some logic
    }  
}

Test case:

[TestClass]
public class AccountTest
{
    [TestMethod]
    public void TestGetAccountDetails()
    {
       using(var mock = new AutoMock.GetLoose())
       {
          var mockAccount = mock.Create<Account>();
          mockAccount.GetAccountDetails();
       }
    }
}

Here I need to mock the savingAccount.Data(); method of SavingAccount class. But when I run the above test, savingAccount object actually calling the Data() method. I don't want to call it, jut want to mock it.

Also I don't to change the above code. I don't want to use the interface.

Upvotes: 2

Views: 6273

Answers (2)

Mihail Vladov
Mihail Vladov

Reputation: 538

It is a bit old question but nevertheless. There are modern mocking frameworks that can mock the new operator and the creation of new objects such as JustMock. Here is an example of how you can mock the SavingAccount class.

// Arrange the what SavingAccount should do 
var savingAccount = new SavingAccount();
Mock.Arrange(() => savingAccount.Data()).DoNothing();

// Arrange that every new creation of SavingAccount will return the object you've created above
Mock.Arrange(() => new SavingAccount()).Returns(savingAccount);

Upvotes: 0

ProgrammingLlama
ProgrammingLlama

Reputation: 38757

I can think of two ways:

Method 1. Create a factory and pass it to Account when you instantiate it. When you need a SavingAccount, call the factory:

    public class Account
    {
        private readonly IAccountFactory _accountFactory;

        public Account(IAccountFactory accountFactory)
        {
            _accountFactory = accountFactory;
        }

        public void GetAccountDetails()  
        {  
            SavingAccount savingAccount = _accountFactory.CreateSavingAccount();
            savingAccount.Data();  

            //Some logic
        }   
    }

Then you can pass an mocked implementation of IAccountFactory into Account. This is the way I recommend doing it, and will make a transition to dependency injection in the future easier if you ever decide to do that.

Method 2. Move instantiation of SavingAccount into a mockable method:

    public class Account  
    {  
        public void GetAccountDetails()  
        {  
            SavingAccount savingAccount = CreateSavingAccount();
            savingAccount.Data();  

            //Some logic
        }

        protected virtual SavingAccount CreateSavingAccount()
        {
            return new SavingAccount();
        }
    }

Now you can mock CreateSavingAccount and have it return a mocked instance of SavingAccount. Note that you will also need to change public void Data() to public virtual void Data() so that you can mock it.

Upvotes: 1

Related Questions