Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Solution.Txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
- Solution is not fully completed however only completed to the extent to prove the approach and concept.
- Dependency injection is used heavily to make is losley coupled and easy to test/mock.
- "static" class declarations is not changed.
- Only basic test cases has been added to prove the point.

CustomerDbContext - NEW:
1. ADO.Net is replaced by EF

IUnitOfWork/UnitOfWork - NEW:
1. New interface and class has been added.

CustomerOrder - NEW:
1. Mapping object, this contains the customer and it's orders if it has any.

VAT - NEW:
1. This is introduced to follow OCP.

App.config - NEW:
1. Connection string is moved here.

CustomerRepository:
1. Multiline ADO.net code is replaced by EF
2. Load All customers implemented

OrderRepository:
1. Code is refactored to make it clean, readable and testable.

OrderService:
1. Refactored to make is extensible/OCP, clean, readable and testable.

Test - NEW:
1. CustomerRepositoryTest
2. OrderRepositoryTest
3. UnitOfWorkTest
4. OrderServiceTest



88 changes: 68 additions & 20 deletions TechTest/AnyCompany.Tests/AnyCompany.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>cd5d577e-bdc9-4dfc-ac6a-b1da474995f3</ProjectGuid>
<ProjectGuid>{1983942E-3221-4387-AE22-28B57C38ECCA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AnyCompany.Tests</RootNamespace>
<AssemblyName>AnyCompany.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -30,24 +39,63 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System"/>

<Reference Include="System.Core"/>
<Reference Include="System.Xml.Linq"/>
<Reference Include="System.Data.DataSetExtensions"/>


<Reference Include="Microsoft.CSharp"/>

<Reference Include="System.Data"/>

<Reference Include="System.Net.Http"/>

<Reference Include="System.Xml"/>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.10.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.10.1\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Class1.cs" />
<Compile Include="CustomerRepositoryTest.cs" />
<Compile Include="OrderRepositoryTest.cs" />
<Compile Include="OrderServiceTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UnitOfWorkTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\AnyCompany\App.config">
<Link>App.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AnyCompany\AnyCompany.csproj">
<Project>{c7e15594-7d8f-4c18-9dd7-14f3fbb1572d}</Project>
<Name>AnyCompany</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
</Project>
2 changes: 2 additions & 0 deletions TechTest/AnyCompany.Tests/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration />
12 changes: 0 additions & 12 deletions TechTest/AnyCompany.Tests/Class1.cs

This file was deleted.

70 changes: 70 additions & 0 deletions TechTest/AnyCompany.Tests/CustomerRepositoryTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using AnyCompany.Entity;
using AnyCompany.Repository;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;

namespace AnyCompany.Tests
{
[TestClass]
public class CustomerRepositoryTest
{
private List<Customer> CustomerList = new List<Customer>();
private Mock<IUnitOfWork> unitOfWork = new Mock<IUnitOfWork>();

public CustomerRepositoryTest()
{
CustomerList.Add(
new Customer()
{
CustomerId = 1,
Country = "UK",
Name = "UKCustomer",
DateOfBirth = new DateTime(1970, 12, 23)
});
CustomerList.Add(
new Customer()
{
CustomerId = 2,
Country = "US",
Name = "USCustomer",
DateOfBirth = new DateTime(1970, 12, 24)
});

unitOfWork.Setup(s => s.Customers).Returns(CustomerList);
}

[TestMethod]
[TestCategory("Customer Repository: Positive Scenario only")]
public void Load_ReturnACustomer()
{
// Arrange
var expectedCustomer = CustomerList.SingleOrDefault<Customer>(c => c.CustomerId == 1);

// Act
var customer = CustomerRepository.Load(expectedCustomer.CustomerId, unitOfWork.Object);

// Assert
unitOfWork.Verify(v => v.Customers, Times.Once);
Assert.AreEqual(expectedCustomer.CustomerId, customer.CustomerId);
}


[TestMethod]
[TestCategory("Customer Repository: Positive Scenario only")]
public void Load_ReturnAllCustomers()
{
// Arrange
var expectedCustomerCount = CustomerList.Count;

// Act
var customers = CustomerRepository.LoadAll(unitOfWork.Object).ToList<Customer>();

// Assert
unitOfWork.Verify(v => v.Customers, Times.Once);
Assert.AreEqual(expectedCustomerCount, customers.Count);
}
}
}
36 changes: 36 additions & 0 deletions TechTest/AnyCompany.Tests/OrderRepositoryTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using AnyCompany.Entity;
using AnyCompany.Repository;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Collections.Generic;

namespace AnyCompany.Tests
{
[TestClass]
public class OrderRepositoryTest
{
private Mock<IUnitOfWork> unitOfWork = new Mock<IUnitOfWork>();

public OrderRepositoryTest()
{
unitOfWork.Setup(s => s.Orders).Returns(new List<Order>());
unitOfWork.Setup(s => s.SaveChangesAsync());
}

[TestMethod]
[TestCategory("Order Repository: Positive Scenario only")]
public void Save_SaveAnOrder()
{
// Arrange
var order = new Order() { CustomerId = 1, OrderId = 1, Amount = 1d, VAT = 0 };
OrderRepository orderRepository = new OrderRepository(unitOfWork.Object);

// Act
orderRepository.Save(order);

// Assert
unitOfWork.Verify(v => v.Orders, Times.Once);
unitOfWork.Verify(v => v.SaveChangesAsync(), Times.Once);
}
}
}
117 changes: 117 additions & 0 deletions TechTest/AnyCompany.Tests/OrderServiceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using AnyCompany.Entity;
using AnyCompany.Repository;
using AnyCompany.Service;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace AnyCompany.Tests
{
[TestClass]
public class OrderServiceTest
{
private List<Customer> CustomerList = new List<Customer>();
private List<VAT> VatList = new List<VAT>();

private Mock<IUnitOfWork> unitOfWork = new Mock<IUnitOfWork>();

public OrderServiceTest()
{
CustomerList.Add(
new Customer()
{
CustomerId = 1,
Country = "UK",
Name = "UKCustomer",
DateOfBirth = new DateTime(1970, 12, 23)
});
CustomerList.Add(
new Customer()
{
CustomerId = 2,
Country = "US",
Name = "USCustomer",
DateOfBirth = new DateTime(1970, 12, 24)
});

unitOfWork.Setup(s => s.Customers).Returns(CustomerList);

// Add items to the VAT list
VatList.Add(
new VAT()
{
ApplyVat = .2d,
Country = "UK"
});
VatList.Add(new VAT()
{
ApplyVat = 0d,
Country = "US"
});

unitOfWork.Setup(s => s.VATs).Returns(VatList);
unitOfWork.Setup(s => s.Orders).Returns(new List<Order>());
unitOfWork.Setup(s => s.SaveChangesAsync());
}

[TestMethod]
[TestCategory("Order Service: Positive Scenario - UK Customer")]
public void Save_SaveAnOrderForUKCustomer()
{
// Arrange
bool expectedOutput = true;
var order = new Order() { CustomerId = 1, OrderId = 1, Amount = 1d, VAT = 0 };
OrderService orderRepository = new OrderService(unitOfWork.Object);

// Act
var actualOutput = orderRepository.PlaceOrder(order);

// Assert
unitOfWork.Verify(v => v.Customers, Times.Once);
unitOfWork.Verify(v => v.VATs, Times.Once);
unitOfWork.Verify(v => v.Orders, Times.Once);
unitOfWork.Verify(v => v.SaveChangesAsync(), Times.Once);
Assert.AreEqual(expectedOutput, actualOutput);
}


[TestMethod]
[TestCategory("Order Service: Positive Scenario - US Customer")]
public void Save_SaveAnOrderForUSCustomer()
{
// Arrange
bool expectedOutput = true;
var order = new Order() { CustomerId = 2, OrderId = 2, Amount = 1d, VAT = 0 };
OrderService orderRepository = new OrderService(unitOfWork.Object);

// Act
var actualOutput = orderRepository.PlaceOrder(order);

// Assert
unitOfWork.Verify(v => v.Customers, Times.Once);
unitOfWork.Verify(v => v.VATs, Times.Once);
unitOfWork.Verify(v => v.Orders, Times.Once);
unitOfWork.Verify(v => v.SaveChangesAsync(), Times.Once);
Assert.AreEqual(expectedOutput, actualOutput);
}



[TestMethod]
[TestCategory("Order Service: Positive Scenario only")]
public void IsValidOrder_ReturnTrue()
{
// Arrange
bool expectedOutput = true;
var order = new Order() { CustomerId = 2, OrderId = 2, Amount = 1d, VAT = 0 };
OrderService orderRepository = new OrderService(unitOfWork.Object);

// Act
var actualOutput = orderRepository.IsValidOrder(order);

// Assert
Assert.AreEqual(expectedOutput, actualOutput);
}
}
}
Loading