简体   繁体   中英

How can we test the stored procedure from the database by using the moq objects in C# Unit Testing?

I have two sp's in the database. I have tested two stored procedures by using the MS Unit test (actual database calls). In deployment, I faced a problem. I could not be able to access the database in the application server. That's why I came up with the moq framework. I need to test those two stored procedures by using the moq objects instead of actual database calls. Can you please suggest me is there any better way to do? Other than MS Unit test like NUnit Test?

What I have tried:

I have tried this. Just I have created one interface(moq repository) and added two methods.

public interface IImintMSNRepository
{  
  bool InsertBulkImportPortfolios(DataTable mSNBulkImportPortfolioTVP,string updatedBy);

    bool InsertBulkImportIndexes(DataTable mSNBulkImportIndexTVP, string updatedBy);
}

I have tested those two methods by using moq like below.

public readonly IImintMSNRepository MockMSNRepository;

public ImintMSNUnitTests()
{

    Mock<IImintMSNRepository> mockRepo = new Mock<IImintMSNRepository>();
    mockRepo.Setup(a => a.InsertBulkImportPortfolios(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);

    mockRepo.Setup(b => b.InsertBulkImportIndexes(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);


    this.MockMSNRepository = mockRepo.Object;
}


[TestMethod]
public void TestPortfolioSPByMOQ()
{
    MSNBulkImportPortfolioTVP ptvp = new MSNBulkImportPortfolioTVP();

    DataRow tvprow = ptvp.NewRow();

    tvprow["PortfolioCode"] = "AutomationMoq1";
    tvprow["PortfolioName"] = "AutomationMoqName1";
    tvprow["ClientName"] = "Thomson Reuters";
    tvprow["RIC"] = "IBM.N";
    tvprow["CalculationMethodology"] = "TRGE";
    tvprow["CalendarEventCode"] = "US";
    tvprow["IsProformaPortfolio"] = 1;
    tvprow["IsParentPortfolio"] = 1;
    tvprow["IsGenerateGroupFragment"] = 1;
    tvprow["IsPushLastTick"] = 1;

    ptvp.Rows.Add(tvprow);

    bool expected = true;
    bool actual;

    actual = this.MockMSNRepository.InsertBulkImportPortfolios(ptvp, "MSNMoqUnitTestProcess");
    Assert.AreEqual(expected, actual);
}

Can anybody please help me?

Consider using localdb or sql server developer on your workstation to test your work. then, use tQLt for unit testing.

I may have misunderstood what you want to do, but testing a stored procedure when the database is unavailable is logically impossible. The stored procedure lives in the database, so you need access to the database to test it.

MOQ is used to create mock (or fake) functions that replace functions that won't work during a unit test. For example if you mock your database call, you can test a higher level function that calls the stored procedure without calling the stored procedure. It would bypass the database call and always return true (as you've done) - but it isn't actually testing the stored procedure.

If you want to test the stored procedures, you're actually writing an Integration Test. I'd recommend putting them in another project and only running it when the database is available (and then you might not need to mock anything).

First you need to answer this question

Consider you actual Repository which inherits from IImintMSNRepository. How is this repository instantiated ?

Assuming it is instantiated using a connection string

//this class is assumption cause you need to test an instance of IImintMSNRepository
public class ImintMSNRepository : IImintMSNRepository
{
    //assuming you need this if you are doing it using a setting object use that  
    public string ConnectionString {get;set;}

    public ImintMSNRepository(string connectionString)
    {
        this.ConnectionString = connectionString;
    }

    public bool InsertBulkImportIndexes(DataTable mSNBulkImportIndexTVP, string updatedBy)
    {
        throw new NotImplementedException();
    }

    public bool InsertBulkImportPortfolios(DataTable mSNBulkImportPortfolioTVP, string updatedBy)
    {
        throw new NotImplementedException();
    }
}

public class ImintMSNUnitTests
    {
        public readonly IImintMSNRepository MockMSNRepository; //Don't mock this or create read only, this needs to be tested

        public  IImintMSNRepository SUTMSNRepository; //THIS IS SUT SYSTEM UNDER TEST

        //you don't need this constructor as well now
        public ImintMSNUnitTests()
        {

            Mock<IImintMSNRepository> mockRepo = new Mock<IImintMSNRepository>();
            mockRepo.Setup(a => a.InsertBulkImportPortfolios(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);

            mockRepo.Setup(b => b.InsertBulkImportIndexes(It.IsAny<DataTable>(), It.IsAny<string>())).Returns(true);


            this.MockMSNRepository = mockRepo.Object;
        }


        [Test]
        public void TestPortfolioSPByMOQ()
        {
            //ARRANGE
            MSNBulkImportPortfolioTVP ptvp = new MSNBulkImportPortfolioTVP();

            DataRow tvprow = ptvp.NewRow();

            tvprow["PortfolioCode"] = "AutomationMoq1";
            tvprow["PortfolioName"] = "AutomationMoqName1";
            tvprow["ClientName"] = "Thomson Reuters";
            tvprow["RIC"] = "IBM.N";
            tvprow["CalculationMethodology"] = "TRGE";
            tvprow["CalendarEventCode"] = "US";
            tvprow["IsProformaPortfolio"] = 1;
            tvprow["IsParentPortfolio"] = 1;
            tvprow["IsGenerateGroupFragment"] = 1;
            tvprow["IsPushLastTick"] = 1;

            ptvp.Rows.Add(tvprow);

            bool expected = true;
            bool actual;

            SUTMSNRepository = new ImintMSNRepository("CONNECTION STRING"); //THIS SHOULD NOT BE A MOCK, THIS SYSTEM UNDER TEST, 
            //MAKE SURE YOU INSTANTIATE THIS AS YOU WANT TO TEST THIS
            //mocking is used mocking the behaviours which is needed to set up the test but not the features you are specifically testing

            //ACT
            actual = this.SUTMSNRepository.InsertBulkImportPortfolios(ptvp, "MSNMoqUnitTestProcess");

            //ASSERT
            Assert.AreEqual(expected, actual);

           //IF ASSERT IS SUCCESSFUL YOU CAN WRITE A CLEANUP METHOD TO REMOVE YOUR UPDATE
        }
    }

Don't mock your repository as that is what you want to test. Instantiate the actual object of your repository and pass in the connection string. Once you do that you can test the assert.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM