C# Disable partly functionality in unit test - c#

I have a function that creates a user, stores in the database and subscribes it to a Mailchimp list.
I have a unit test that tests this function.
Now I do want to test this function, but I dont want the 'mocked' user to be added to the mailinglist.
Is there a way to partly exclude code execution when a function is run in a unit test mode?
So for example I have this function (simplyfied)
public async Task<CreateUserResponse> Create(CreateUserRequest createRequest){
//Save user to database
var encryptedPassword = encryptor.EncryptPassword(createRequest.Password, salt);
var user = new UserDomain(){
EmailAddress = createRequest.EmailAddress,
Password = encryptedPassword,
Salt = salt
}
_dbContext.Users.Add(user);
//Subscribe to mailing list
var mailChimpAdapter = new MailChimpAdapter(_configuration);
mailChimpAdapter.Subscribe(user);
return new CreateUserResponse(user);
}
Now I want to run a unit test to test that function but without subscribing it.
Best I can think of is using a variable in the config file and read it out inside the function. But maybe there is a better way?

One way is to extract an interface from MailChimpAdapter (say, IMailChimpAdapter) and then use it to mock the constructor and the subscribe method. You can use a library like Moq.
Check this for a quick intro :

Related

Stopping a test in C# visual studio if no data exist with smoke test

I have a pack of smoke test that run and randomly pull data from a table and search by that data in another method and assert after. The test will fail if no data exist. I have a reusable method called RandomVinSelect(). I want to stop the test if there is no data. I have searched for test result warnings that test could not be ran instead of failing the test. At this point I am stumped. This is the code I have I do not want to run the lines after UI.RandomVINSelect if no data found. I am thinking there may not be a way for this using Xunit and it would just be pass or fail...
public static string RandomVinSelect(this Browser ui, string table,
string selector)
{
//I want to stop test here if no data exist or create a dataexist
//method that stops a test.
int rows = ui.GetMultiple(table).Count;
Random num = new Random();
string randomnum = Convert.ToString(num.Next(1, rows));
string newselector = selector.Replace("1", randomnum);
string vin = ui.Get(newselector).Text;
return vin;
}
Perhaps just put smoke tests in a separate test package or collection and include a test that just checks to see if it can get data, then when you run this group of tests if that first test fails you know it is just due to no data being available.
Not ideal but might be good enough?
I installed the new nuget package(xunit.SkippableFact) added [SkippableFact] to my smoke test. Then I created a method that can be called to check and see if data is available and runs a Skip.If(condition,"my message") within that method and closes the test early if no data is present. Then in the Test Explorer show a warning symbol.
public static void IsDataAvaiable(this Browser ui)
{
bool data = true;
string pagecount = ui.GetPageCount();
if (pagecount == "0") data = false;
Skip.If(data == false, "The test could not run because no data available for validation.");
}

NUnit get results programmatically during run session

again i am trying to do something and not sure if it is possible. i want to run my Nunit tests and after each test is run, i want to output the result to my ui. the ui is custom and is used by my test team to run and see test results. when i say it is used, it is not developed yet (fully) :) - bringing me to this question.
my code so far
TestPackage package = new TestPackage(path);
RemoteTestRunner remote = new RemoteTestRunner();
remote.Load(package);
TestResult result = remote.Run(new NullListener(), TestFilter.Empty, true, LoggingThreshold.All);
while (remote.Running)
{
// want to capture results here
if (result.HasResults)
// i can never get here while test is running
}
How about dumping the results as XML into shared location. And then your UI can parse/pick up from that location
Also try to use common XML schema so that you can easily serialize/deserialize back from XML to C# object and vice versa
We have done smth similar in the past and above scenario has worked quite well

Is it possible to keep NDbUnit test data in separate XML files?

I'm looking at using NDbUnit to help with the unit testing of an application. As the question title states, I'm wondering if it is possible to keep NDbUnit test data in separate XML files. I have noticed already that my single test data XML file is quite big and could start to become unmanageable when I add a few more entities to it.
Now, having read this question it looks as if it's not possible but I would just like to be sure.
If it helps, this is sample code which illustrates the problem. The idea is that programs are associated with vendors. I have set up test data containing 3 vendors, the second one of which has 3 programs. TestData.xml contains all of the test data for all of the vendors and programs. When I use it, the unit test passes as expected. If I try to read the individual XML file in separately using multiple calls to db.PerformDbOperation(DbOperationFlag.CleanInsertIdentity); it seems as if the second call overwrites whatever was done in the first one.
private const string xmlSchema = #"..\..\schema.xsd";
// All of the test data in one file.
private const string xmlData = #"..\..\XML Data\TestData.xml";
// Individual test data files.
private const string vendorData = #"..\..\XML Data\Vendor_TestData.xml";
private const string programData = #"..\..\XML Data\Program_TestData.xml";
public void WorkingExampleTest()
{
INDbUnitTest db = new SqlDbUnitTest(connectionString);
db.ReadXmlSchema(xmlSchema);
db.ReadXml(xmlData);
db.PerformDbOperation(DbOperationFlag.CleanInsertIdentity);
VendorCollection vendors = VendorController.List();
Assert.IsNotNull(vendors);
ProgramCollection collection = VendorController.GetPrograms(vendors[1].VendorID);
Assert.IsNotNull(collection);
Assert.IsTrue(collection.Count == 3);
}
public void NotWorkingExampleTest()
{
INDbUnitTest db = new SqlDbUnitTest(connectionString);
db.ReadXmlSchema(xmlSchema);
db.ReadXml(vendorData);
db.PerformDbOperation(DbOperationFlag.CleanInsertIdentity);
db.ReadXml(programData);
db.PerformDbOperation(DbOperationFlag.CleanInsertIdentity);
VendorCollection vendors = VendorController.List();
Assert.IsNotNull(vendors);
// This line throws an ArgumentOutOfRangeException because there are no vendors in the collection.
ProgramCollection collection = VendorController.GetPrograms(vendors[1].VendorID);
Assert.IsNotNull(collection);
Assert.IsTrue(collection.Count == 3);
}
This does work:
Watch out for the meaning of the DbOperationFlag value you are using; the "Clean" part of "CleanInsertIdentity" means "clean out the existing records before performing the insert-identity part of the process".
See http://code.google.com/p/ndbunit/source/browse/trunk/NDbUnit.Core/DbOperationFlag.cs for more info on the possible enum values.
You might try the same process with either Insert or InsertIdentity to see if you can achieve what you are after, but by design CleanInsertIdentity isn't going to work for this scenario :)

Using TDD with OpenXml-SDK

I have started using a TDD approach to develop a small app that reads data from Excel files. Using a repository pattern type approach I have come to a hurdle which baffles me.
In order to read the Excel files, I am using the OpenXml-SDK. Now typically reading from an Excel file using the SDK requires several if not more steps to actually get the values you want to read.
The approach I have taken thus far is reflected in the following test and accompanying function.
[Test]
public void GetRateData_ShouldReturn_SpreadSheetDocument()
{
//Arrange
var fpBuilder = new Mock<IDirectoryBuilder>();
fpBuilder.Setup(fp => fp.FullPath()).Returns(It.IsAny<string>());
var doc = new Mock<IOpenXmlUtilities>();
doc.Setup(d => d.OpenReadOnlySpreadSheet(It.IsAny<string>()))
.Returns(Mock.Of<SpreadsheetDocument>());
swapData = new SwapRatesRepository(fpBuilder.Object, doc.Object);
//Act
var result = swapData.GetRateData();
//Assert
doc.Verify();
fpBuilder.Verify();
}
public class SwapRatesRepository: IRatesRepository<SwapRates>
{
private const string SWAP_DATA_FILENAME = "DATE_MKT_ZAR_SWAPFRA1.xlsx";
private IDirectoryBuilder builder;
private IOpenXmlUtilities openUtils;
public SwapRatesRepository(IDirectoryBuilder builder)
{
// TODO: Complete member initialization
this.builder = builder;
}
public SwapRatesRepository(IDirectoryBuilder builder,
IOpenXmlUtilities openUtils)
{
// TODO: Complete member initialization
this.builder = builder;
this.openUtils = openUtils;
}
public SwapRates GetRateData()
{
// determine the path of the file based on the date
builder.FileName = SWAP_DATA_FILENAME;
var path = builder.FullPath();
// open the excel file
using(SpreadsheetDocument doc = openUtils.OpenReadOnlySpreadSheet(path))
{
//WorkbookPart wkBookPart = doc.WorkbookPart;
//WorksheetPart wkSheetPart = wkBookPart.WorksheetParts.First();
//SheetData sheetData = wkSheetPart.Worksheet
// .GetFirstChild<SheetData>();
}
return new SwapRates(); // ignore this class for now, design later
}
}
However, the next steps after the spreadsheet is open would be to actually start interrogating the Excel object model to retrieve the values. As noted above, I making use of mocks for anything open xml related. However, in some cases the objects can't be mocked(or I don't know how to mock them since they are static). That gave rise to IOpenXmlUtilities which are merely simple wrapper calls into the OpenXml-SDK.
In terms of design, we know that reading data from excel files is a short term solution (6-8 months), so these tests only affect the repository/data access for the moment.
Obviously I don't want to leave the TDD approach(as tempting as it is), so I am looking for advise and guidance on how to continue my TDD endeavours with the OpenXml SDK. The other aspect relates to mocking - I am confused as to when and how to use mocks in this case. I don't want to unknowingly writes tests that test the OpenXml-SDK.
*Side note: I know that the SOLIDity of my design can be improved but I leaving that for now. I have a set of separate tests that relate to the builder object. The other side effect that may occur is the design of an OpenXML-SDK wrapper library.
Edit: Unbeknown at the time, by creating the OpenXML-SDK wrappers for the OpenXML-SDK, i have used a design pattern similar (or exact) called the Adaptor pattern.
If you can't mock it and can't create a small unittest, it might be better to take it to a higher level and make a scenario test. You can use the [TestInitialize] and [TestCleanup] methods to create a setup for the test.
using Pex and Moles might be another way to get it tested.

How do I specify test method parameters with TestDriven.NET?

I'm writing unit tests with NUnit and the TestDriven.NET plugin. I'd like to provide parameters to a test method like this :
[TestFixture]
public class MyTests
{
[Test]
public void TestLogin(string userName, string password)
{
// ...
}
...
}
As you can see, these parameters are private data, so I don't want to hard-code them or put them in a file. Actually I don't want to write them anywhere, I want to be prompted each time I run the test.
When I try to run this test, I get the following message in the output window :
TestCase 'MyProject.MyTests.TestLogin' not executed: No arguments were provided
So my question is, how do I provide these parameters ? I expected TestDriven.NET to display a prompt so that I can enter the values, but it didn't...
Sorry if my question seems stupid, the answer is probably very simple, but I couldn't find anything useful on Google...
EDIT: I just found a way to do it, but it's a dirty trick...
[Test, TestCaseSource("PromptCredentials")]
public void TestLogin(string userName, string password)
{
// ...
}
static object[] PromptCredentials
{
get
{
string userName = Interaction.InputBox("Enter user name", "Test parameters", "", -1, -1);
string password = Interaction.InputBox("Enter password", "Test parameters", "", -1, -1);
return new object[]
{
new object[] { userName, password }
};
}
}
I'm still interested in a better solution...
Use the TestCase attribute.
[TestCase("User1", "")]
[TestCase("", "Pass123")]
[TestCase("xxxxxx", "xxxxxx")]
public void TestLogin(string userName, string password)
{
// ...
}
Unit Tests should normally not take any parameters. You create the necessary data within the test itself.
The expected value
You call your method you want to test passing the necessary arguments
You compare the result with the expected value and the returned value from your tested method
MS Unit tests don't allow the passing of parameters to tests. Instead you need to create Datadriven Unit tests. Try the link, it may help you.
As I mentioned. I wouldn't declare passing arguments to unit tests itself good practice.
Update: I was young :). Consider Sarfraz's answer instead on how to pass parameters to NUnit tests.
I think you can solve this problem by using the RowTest plugin for NUnit found here http://www.andreas-schlapsi.com/2008/01/29/rowtest-extension-120/
You can create simple Data-Driven Tests where the test data is provided by [Row] attributes. So here is an example of a test that is run over and over again with different parameters:
[TestFixture]
public class RowTestSample
{
[RowTest]
[Row( 1000, 10, 100.0000)]
[Row(-1000, 10, -100.0000)]
[Row( 1000, 7, 142.85715)]
[Row( 1000, 0.00001, 100000000)]
[Row(4195835, 3145729, 1.3338196)]
public void DivisionTest(double numerator, double denominator, double result)
{
Assert.AreEqual(result, numerator / denominator, 0.00001);
}
}
I agree with the other answers that passing arguments may not be best practise, but neither is hard coding credentials or server addresses that may change at some point.
Inspired by the suggested solution in question, I simply read console input instead of using input boxes. The arguments are saved in a file. When starting a the tests, the file is redirected and to be read from some initialization function that should be called before any test cases run.
nunit tests.dll < test.config
This avoids user interaction and should be runnable by any automation script. Downside is that the password still has to be saved somewhere, but at least it can be saved local on the testers machine and is easy to change.
This was for a project, where excel sheets containing the tests (not unit tests by definition) were used to let others create test cases for a bigger server side project without changing any code. It would have been bad if all test cases had to be forced in a single giant excel sheet. Also there was no CI, just many testing environments on different servers.
Create a class and store the details of the required variable in const.
Note: If you create variable as static then it won't work in the Nunit framework.
public Class Credential
{
public const string PUBLIC_USER = "PublicUser#gmail.com";
public const string PASSWORD= "password123";
}
[Test]
[TestCase(Credential.PUBLIC_USER, Credential.PASSWORD)]
public void VerifyLogin(string username, string password)

Categories

Resources