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.