Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.


DNN Unit/Integration Testing – Part 2

Introduction

This is the second article to guide those who would like to contribute to DNN Platform on how to write tests. In this article, I will expand on the first article here. I will base the tests on a real code that was contributed by some community members.

Deciding How and Where to Add Tests

Sometimes, it can be hard to decide what tests and how many to add, and where to add them. In theory, robust software requires unit or integration tests written for every single branch. In practice, this can be very tedious, time consuming, and at times unnecessary. Therefore, you need to use common sense to test the various scenarios you can think of without overdoing it or repeating yourself. But, in general, there should be two types of tests added: positive and negative. Positive tests are those which follow the normal expected flow, and contain valid input data, and produce the expected results. Negative tests are those which have one or more invalid input data, and doesn’t produce the expected result. For more description of these test types you can refer to this post. Also, depending on the change that was made to the code, we might need one of these but not both or there might be an already existing tests to test them but we need to add more tests to validate the changes we introduced in the code.

Adding Your First Unit Test(s)

As I explained in the first article, when writing unit tests, we should try to avoid using any existing site and target base code without database or file system. But due to the large amount of the Platform’s legacy code we might not be able to avoid the need for site or database. To some extent, we can achieve this through mocking some base objects. I will explain more below when adding new tests. Also, you need to be familiar with mocking and writing NUnit tests to be able to follow up.

Pull Request 1915

Through this tutorial, I will refer to this pull request (PR) for the DNN Platform https://github.com/dnnsoftware/Dnn.Platform/pull/1915. This PR is addressing an issue in SMTP host setting value that used to accept any value without validating it before sending a test email. The details of this issue can be seen in our bug tracking system, Jira, here.

DotNetNuke.Services.Mail.Mail method

When looking at the class “DotNetNuke.Services.Mail.Mail” in the DNN Platform source code that was fixed we notice the checks for the SMTP server name and port were insufficient and caused exceptions to be thrown. The introduced changes fixed this by using proper checking to prevent throwing an exception and a proper message is being returned to the caller. These changes should be captured in the tests we would like to create. Thus, we need to validate that no exceptions are thrown now and that the proper error message is returned. We should notice that this error message is using localization; therefore, we need to take this into consideration in the tests. Luckily, the DNN testing utilities provide ways to mock many various controllers and providers of the base DNN library classes and this allows us to write our tests without requiring the site itself, the database, and resource files being physically installed and present. So, let’s proceed.

DotNetNuke.Tests.Core project

As we decided to write unit tests and sending mail is a core feature, then we will add the tests under the “DotNetNuke.Tests.Core” project. To do this, we add a folder called Mail under this project and add a source file named “MailTests.cs” there as shown in the next figure.

 
Next, we need to create a skeleton for our tests. To do so, we modify the by decorating it with the proper NUnit attribute, and create the skeleton of our positive and negative tests. Until now we haven’t decided what to write and how to write it yet. The skeleton should look something like this:

Skeleton Test Class

using NUnit.Framework;

namespace DotNetNuke.Tests.Core.Mail

{

    [TestFixture]

    public class MailTests

    {

        /// <summary>

        /// This represents the positive path for our tests

        /// The tests checks for good SMTP server name and port syntax and not

        /// about the send result; as we will not be sending emails because

        /// the server doesn't exist.

        /// </summary>

        [TestCase("GoodSmtpName")]

        public void Valid_SMTP_Server_Name_Should_Pass(string smtpServerName)

        {

            Assert.Fail();

        }

        /// <summary>

        /// This represents the negative path for our tests

        /// The tests checks for bad SMTP server name and port syntax and

        /// checks for text returned from the called method

        /// </summary>

        [TestCase("BadSmtpName: and port")]

        public void Invalid_SMTP_Server_Name_Should_Fail(string smtpServerName)

        {

            Assert.Fail();

        }

    }

}

 

Notice that we set our tests to fail initially until we write the proper tests that make them pass. Now we proceed to add the test body for the positive test by calling the “SendMail” method passing a valid server name. But because we don’t need to physically send the email, we need to use an SMTP server name that doesn’t resolve to an actual mail server. The body of the positive method will be something as follows (all parameters are valid including the SMTP server name):

        [TestCase("GoodSmtpName")]

        public void Valid_SMTP_Server_Name_Should_Pass(string smtpServerName)

        {

            var result = DotNetNuke.Services.Mail.Mail.SendMail(

                mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            Assert.AreEqual(string.Empty, result);

        }

Mocking

But when we run the test we see that it failed due to many exceptions, unrelated to calling the send mail method. Here is what we can see in this case:

System.NullReferenceException : Object reference not set to an instance of an object.

   at DotNetNuke.Common.Globals.get_Status() in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Common\Globals.cs:line 589

   at DotNetNuke.Services.Log.EventLog.LogController.AddLog(LogInfo logInfo) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Services\Log\EventLog\LogController.cs:line 181

   at DotNetNuke.Services.Log.EventLog.ExceptionLogController.AddLog(Exception objException, LogInfo log, ExceptionLogType logType) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Services\Log\EventLog\ExceptionLogController.cs:line 136

   at DotNetNuke.Services.Log.EventLog.ExceptionLogController.AddLog(Exception objException, ExceptionLogType logType) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Services\Log\EventLog\ExceptionLogController.cs:line 97

   at DotNetNuke.Services.Exceptions.Exceptions.LogException(Exception exc) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Services\Exceptions\Exceptions.cs:line 473

   at DotNetNuke.Common.Utilities.DataCache.GetCachedDataFromDictionary(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Common\Utilities\DataCache.cs:line 599

   at DotNetNuke.Common.Utilities.DataCache.GetCachedData[TObject](CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired, Boolean storeInDictionary) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Common\Utilities\DataCache.cs:line 625

   at DotNetNuke.Common.Utilities.CBO.GetCachedObject[TObject](CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired, Boolean saveInDictionary) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Common\Utilities\CBO.cs:line 925

   at DotNetNuke.Entities.Controllers.HostController.GetSettings() in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Entities\Controllers\HostController.cs:line 186

   at DotNetNuke.Entities.Controllers.HostController.GetString(String key, String defaultValue) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Entities\Controllers\HostController.cs:line 240

   at DotNetNuke.Entities.Controllers.HostController.GetString(String key) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Entities\Controllers\HostController.cs:line 226

   at DotNetNuke.Entities.Host.Host.GetSmtpSetting(String settingName) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Entities\Host\Host.cs:line 1323

   at DotNetNuke.Entities.Host.Host.get_SMTPAuthentication() in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Entities\Host\Host.cs:line 1278

   at DotNetNuke.Services.Mail.Mail.SendMail(String mailFrom, String mailSender, String mailTo, String cc, String bcc, String replyTo, MailPriority priority, String subject, MailFormat bodyFormat, Encoding bodyEncoding, String body, List`1 attachments, String smtpServer, String smtpAuthentication, String smtpUsername, String smtpPassword, Boolean smtpEnableSSL) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Library\Services\Mail\Mail.cs:line 538

   at DotNetNuke.Tests.Core.Mail.MailTests.Valid_SMTP_Server_Name_Should_Pass(String smtpServerName) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Tests\DotNetNuke.Tests.Core\Mail\MailTests.cs:line 43

 

 So, what is the issue? As I said above, we don’t expect the actual site being installed to run the unit tests, therefore we don’t have fully initialized variables and objects from the site’s database and files. This requires mocking. Mocking is creating a fake class instance to server our purpose of calling stubbed methods that are not the actual method in the code and we control the returned results of these methods. The full details are beyond the scope of this article and you need to search online for more details.

Mocking Data Provider

For this to work, we need to add mocks for a few items in our system. First, we need to mock the data provider in order to override database logging. This is provided by DNN and you just need to add these lines at the top of the class which will be executed each time a test is executed as follows:

        private Mock<DataProvider> _mockDataProvider;

        [SetUp]

        public void SetUp()

        {

            ComponentFactory.Container = new SimpleContainer();

            _mockDataProvider = MockComponentProvider.CreateDataProvider();

            //Standard DataProvider path for logging

            _mockDataProvider.Setup(d => d.GetProviderPath()).Returns("");

        }

 

Still Failing!

Now when we run the positive test, we see it is still failing but due to a different reason which is the return result from the call is not as expected. The error we see is as follows:

  Expected string length 0 but was 77. Strings differ at index 0.

  Expected: <string.Empty>

  But was:  " Failure sending mail.\r\nThe remote name could not be resolved..."

  -----------^

   at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression, String message, Object[] args)

   at DotNetNuke.Tests.Core.Mail.MailTests.Valid_SMTP_Server_Name_Should_Pass(String smtpServerName) in C:\Projects\DnnSoftware\Dnn.Platform\DNN Platform\Tests\DotNetNuke.Tests.Core\Mail\MailTests.cs:line 47

 

Modifying the Test

As we explained before, the process of sending the email through the SMTP server is not in the scope of this test and fails. Therefore, we need to change the test check at the end to take this into consideration and check for the expected return result. To do so, we need to change the positive test to look like the following:

        [TestCase("GoodSmtpName")]

        public void Valid_SMTP_Server_Name_Should_Pass(string smtpServerName)

        {

            var result = DotNetNuke.Services.Mail.Mail.SendMail(

                mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            var expected = $@" Failure sending mail." + Environment.NewLine +

                           @"The remote name could not be resolved: 'GoodSmtpName'";

            Assert.AreEqual(expected, result);

        }

 

Now when we run the positive test, it passes without any error.

Using Same Test to Add Multiple Scenarios

To add more scenarios to the positive test, we can add the following test cases before the test definition which will give us a total of 6 cases to validate.

        [TestCase("GoodSmtpName")]

        [TestCase("GoodSmtpName:1")]

        [TestCase("GoodSmtpName:12")]

        [TestCase("GoodSmtpName:123")]

        [TestCase("GoodSmtpName:1234")]

        [TestCase("GoodSmtpName:65535")]

 

Negative Tests

This concludes our positive tests. Now let’s turn towards the negative tests now. To consider no exceptions are thrown now, we need to assert this in the method. We do this by changing the test as follows:

        [TestCase("BadSmtpName: and port")]

        public void Invalid_SMTP_Server_Name_Should_Fail(string smtpServerName)

        {

            Assert.DoesNotThrow(() =>

            {

                DotNetNuke.Services.Mail.Mail.SendMail(

                    mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                    replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                    bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                    attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                    smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            });

        }

 

Can we do better?

This will pass when we run the test. But this is insufficient, as we can have other errors than validating the server name being returned. Therefore, we need to add another assertion to make sure the cause of the error is due to malformed server name string. As such, we must check the returned value from the send mail call. Upon inspecting the code which is executed when an error occurs, we see that is executes this code path in the Mail class:

            else

            {

                retValue = Localize.GetString("SMTPConfigurationProblem");

            }

This will tell us we need to check for the value of the returned string from the localization provider. If we look for this value in the resources files, we see the following:

  <data name="SMTPConfigurationProblem.Text" xml:space="preserve">

    <value>There is a problem with the configuration of your SMTP Server.  Mail was not sent.</value>

  </data>

Now, we can test directly against this by changing the negative test to the following:

        [TestCase("BadSmtpName: and port")]

        public void Invalid_SMTP_Server_Name_Should_Fail(string smtpServerName)

        {

            string result = null;

            Assert.DoesNotThrow(() =>

            {

                result = DotNetNuke.Services.Mail.Mail.SendMail(

                    mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                    replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                    bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                    attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                    smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            });

            var expected = $@"There is a problem with the configuration of your SMTP Server.  Mail was not sent.";

            Assert.AreEqual(expected, result);

        }

 

Why is it still failing?

But, still this fails the last assertion as the result will be NULL. In order to overcome this, we need to mock the localization provider. This can be done by adding the mocking code inside the negative test itself (as it is not shared with the positive test) and stubbing the expected return value as we need it to be. We must to do this to avoid the cases when the resources file string might change at any time or we run the tests under non- “us-EN” locale which will cause the test to fail. The following code shows how this is done in our negative test:

        [TestCase("BadSmtpName: and port")]

        public void Invalid_SMTP_Server_Name_Should_Fail(string smtpServerName)

        {

            const string SmtpConfigurationProblem_Key = "SMTPConfigurationProblem";

            const string SmtpConfigurationProblem_Value = "Invalid SMTP Server name and port. Mail not sent!";

            var localizationMock = MockComponentProvider.CreateLocalizationProvider();

            // mock the expected return error string(s) from the SendMail method

            localizationMock.Setup(l => l.GetString(SmtpConfigurationProblem_Key,

                It.IsAny<string>(), It.IsAny<string>(), It.IsAny<PortalSettings>(), It.IsAny<bool>()))

                .Returns(SmtpConfigurationProblem_Value);

            string result = null;

            Assert.DoesNotThrow(() =>

            {

                result = DotNetNuke.Services.Mail.Mail.SendMail(

                    mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                    replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                    bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                    attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                    smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            });

            Assert.AreEqual(SmtpConfigurationProblem_Value, result);

        }

And, voila, the test passes without errors. Note that in mocking the localized string, we ignored the thread culture / locale of the environment this test runs under by providing our own string for any culture (the second parameter in “GetString” which is called as “It.IsAny<string>()”).

Adding Few More Tests Cases

Now we can add more negative test cases by replacing this line

            [TestCase("BadSmtpName: and port")]

With the following various cases:

        [TestCase("GoodSmtpName:")]        // invalid syntax; must not have colon in name

        [TestCase(":5000")]                // invalid syntax; missing server name

        [TestCase("GoodSmtpName::1000")]   // invalid syntax; double colons

        [TestCase("GoodSmtpName:posrtYY")] // invalid port; contains text

        [TestCase("GoodSmtpName:123456")]  // invalid port; greater than 65535

        [TestCase("GoodSmtpName:-1234")]   // invalid port; negative not allowed 

Now running the full set of tests will pass as appearing in this image.

 

Final Tests Source Code

Below is the full source code for the final version of the “MailTests.cs” file:

using System;

using System.Collections.Generic;

using System.Net.Mail;

using System.Text;

using DotNetNuke.ComponentModel;

using DotNetNuke.Data;

using DotNetNuke.Entities.Portals;

using DotNetNuke.Services.Mail;

using DotNetNuke.Tests.Utilities.Mocks;

using Moq;

using NUnit.Framework;

namespace DotNetNuke.Tests.Core.Mail

{

    [TestFixture]

    public class MailTests

    {

        private Mock<DataProvider> _mockDataProvider;

        [SetUp]

        public void SetUp()

        {

            ComponentFactory.Container = new SimpleContainer();

            _mockDataProvider = MockComponentProvider.CreateDataProvider();

            //Standard DataProvider path for logging

            _mockDataProvider.Setup(d => d.GetProviderPath()).Returns("");

        }

        /// <summary>

        /// This represents the positive path for our tests

        /// The tests checks for good SMTP server name and port syntax and not

        /// about the send result; as we will not be sending emails because

        /// the server doesn't exist.

        /// </summary>

        [TestCase("GoodSmtpName")]

        [TestCase("GoodSmtpName:1")]

        [TestCase("GoodSmtpName:12")]

        [TestCase("GoodSmtpName:123")]

        [TestCase("GoodSmtpName:1234")]

        [TestCase("GoodSmtpName:65535")]

        public void Valid_SMTP_Server_Name_Should_Pass(string smtpServerName)

        {

            var result = DotNetNuke.Services.Mail.Mail.SendMail(

                mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            var expected = $@" Failure sending mail." + Environment.NewLine +

                           @"The remote name could not be resolved: 'GoodSmtpName'";

            Assert.AreEqual(expected, result);

        }

        /// <summary>

        /// This represents the negative path for our tests

        /// The tests checks for bad SMTP server name and port syntax and

        /// checks for text returned from the called method

        /// </summary>

        [TestCase("GoodSmtpName:")]        // invalid syntax; must not have colon in name

        [TestCase(":5000")]                // invalid syntax; missing server name

        [TestCase("GoodSmtpName::1000")]   // invalid syntax; double colons

        [TestCase("GoodSmtpName:posrtYY")] // invalid port; contains text

        [TestCase("GoodSmtpName:123456")]  // invalid port; greater than 65535

        [TestCase("GoodSmtpName:-1234")]   // invalid port; negative not allowed

        public void Invalid_SMTP_Server_Name_Should_Fail(string smtpServerName)

        {

            const string SmtpConfigurationProblem_Key = "SMTPConfigurationProblem";

            const string SmtpConfigurationProblem_Value = "Invalid SMTP Server name and port. Mail not sent!";

            var localizationMock = MockComponentProvider.CreateLocalizationProvider();

            // mock the expected return error string(s) from the SendMail method

            localizationMock.Setup(l => l.GetString(SmtpConfigurationProblem_Key,

                It.IsAny<string>(), It.IsAny<string>(), It.IsAny<PortalSettings>(), It.IsAny<bool>()))

                .Returns(SmtpConfigurationProblem_Value);

            string result = null;

            Assert.DoesNotThrow(() =>

            {

                result = DotNetNuke.Services.Mail.Mail.SendMail(

                    mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                    replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                    bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                    attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                    smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            });

            Assert.AreEqual(SmtpConfigurationProblem_Value, result);

        }

    }

}using System;

using System.Collections.Generic;

using System.Net.Mail;

using System.Text;

using DotNetNuke.ComponentModel;

using DotNetNuke.Data;

using DotNetNuke.Entities.Portals;

using DotNetNuke.Services.Mail;

using DotNetNuke.Tests.Utilities.Mocks;

using Moq;

using NUnit.Framework;

namespace DotNetNuke.Tests.Core.Mail

{

    [TestFixture]

    public class MailTests

    {

        private Mock<DataProvider> _mockDataProvider;

        [SetUp]

        public void SetUp()

        {

            ComponentFactory.Container = new SimpleContainer();

            _mockDataProvider = MockComponentProvider.CreateDataProvider();

            //Standard DataProvider path for logging

            _mockDataProvider.Setup(d => d.GetProviderPath()).Returns("");

        }

        /// <summary>

        /// This represents the positive path for our tests

        /// The tests checks for good SMTP server name and port syntax and not

        /// about the send result; as we will not be sending emails because

        /// the server doesn't exist.

        /// </summary>

        [TestCase("GoodSmtpName")]

        [TestCase("GoodSmtpName:1")]

        [TestCase("GoodSmtpName:12")]

        [TestCase("GoodSmtpName:123")]

        [TestCase("GoodSmtpName:1234")]

        [TestCase("GoodSmtpName:65535")]

        public void Valid_SMTP_Server_Name_Should_Pass(string smtpServerName)

        {

            var result = DotNetNuke.Services.Mail.Mail.SendMail(

                mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            var expected = $@" Failure sending mail." + Environment.NewLine +

                           @"The remote name could not be resolved: 'GoodSmtpName'";

            Assert.AreEqual(expected, result);

        }

        /// <summary>

        /// This represents the negative path for our tests

        /// The tests checks for bad SMTP server name and port syntax and

        /// checks for text returned from the called method

        /// </summary>

        [TestCase("GoodSmtpName:")]        // invalid syntax; must not have colon in name

        [TestCase(":5000")]                // invalid syntax; missing server name

        [TestCase("GoodSmtpName::1000")]   // invalid syntax; double colons

        [TestCase("GoodSmtpName:posrtYY")] // invalid port; contains text

        [TestCase("GoodSmtpName:123456")]  // invalid port; greater than 65535

        [TestCase("GoodSmtpName:-1234")]   // invalid port; negative not allowed

        public void Invalid_SMTP_Server_Name_Should_Fail(string smtpServerName)

        {

            const string SmtpConfigurationProblem_Key = "SMTPConfigurationProblem";

            const string SmtpConfigurationProblem_Value = "Invalid SMTP Server name and port. Mail not sent!";

            var localizationMock = MockComponentProvider.CreateLocalizationProvider();

            // mock the expected return error string(s) from the SendMail method

            localizationMock.Setup(l => l.GetString(SmtpConfigurationProblem_Key,

                It.IsAny<string>(), It.IsAny<string>(), It.IsAny<PortalSettings>(), It.IsAny<bool>()))

                .Returns(SmtpConfigurationProblem_Value);

            string result = null;

            Assert.DoesNotThrow(() =>

            {

                result = DotNetNuke.Services.Mail.Mail.SendMail(

                    mailFrom: "from@lvh.me", mailTo: "to@lvh.me", mailSender: "sender@lvh.me", cc: "", bcc: "",

                    replyTo: "", priority: DotNetNuke.Services.Mail.MailPriority.Normal, subject: "Subject",

                    bodyFormat: MailFormat.Text, bodyEncoding: Encoding.UTF8, body: "test email body",

                    attachments: new List<Attachment>(), smtpServer: smtpServerName, smtpAuthentication: "",

                    smtpUsername: "", smtpPassword: "", smtpEnableSSL: false);

            });

            Assert.AreEqual(SmtpConfigurationProblem_Value, result);

        }

    }

}

 

Submitting Your Tests

So, you have written these tests what next? After completing these tests and making sure they are all passing, you need to commit these along with the source code that you have fixed and submit a pull request to be processed by the DNN development team.

In order to comply with the contribution submission, you need to have a look at this contributing guide.

 

Summary

I just touched the basics of adding unit tests in DNN. The existing unit tests have a lot more examples for you to learn from. So, don’t hesitate to have a look and send me any questions you have by posting them as comments to this series of articles.

Comments

There are currently no comments, be the first to post one.

Comment Form

Only registered users may post comments.

NewsArchives


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Daniels (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Steven Fisher (1)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out