This commit is contained in:
nbilal 2016-05-19 09:54:29 -07:00
Родитель 7512fcc037
Коммит bb9b4b4501
72 изменённых файлов: 3408 добавлений и 1 удалений

200
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,200 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.lock.json
*.generated.cs
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
SimpleStubsDlls
# Visual Studo 2015 cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
*.[Cc]ache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt

266
Documentation/Tutorial.md Normal file
Просмотреть файл

@ -0,0 +1,266 @@
# SimpleStubs tutorial
In this tutorial we will show how to install and use SimpleStubs.
## Installation
To install SimpleStubs, simply install the `Etg.SimpleStubs` NuGet package to your unit test project.
Once installed, SimpleStubs will create stubs for all interfaces (`public` interfaces and optionally `internal` interfaces) in all referenced projects. No stubs will be generated for external libraries (dlls) but that's a feature we're considering.
The generated stubs will be added to the `Properties\SimpleStubs.generated.cs` file which will be regenerated every time the project is built (the stubs will be generated before the build and will be compiled as part of the build, so you don't need to worry about any of that). Because the stubs are regenerated every time, modifying the stubs manually has no effect (if you really want to modify a stub, copy it to a different file).
**Important note for UWP**: Because of a limitation in NuGet support for UWP (see discussion [here](https://github.com/NuGet/Home/wiki/Bringing-back-content-support,-September-24th,-2015)), the `Properties\SimpleStubs.generated.cs` file will not be automatically added to UWP projects and must be manually added (simply add the file to the `Properties` folder of your test project).
## Api
Let's consider the following interface and look at how we can use SimpleStubs to create stubs for it.
```csharp
public interface IPhoneBook
{
long GetContactPhoneNumber(string firstName, string lastName);
long MyNumber { get; set; }
event EventHandler<long> PhoneNumberChanged;
}
```
### Stubbing methods
```csharp
var stub = new StubIPhoneBook
{
GetContactPhoneNumber_String_String = (fn, ln) =>
{
return 6041234567;
}
};
```
You can also copy and verify the parameters values:
```csharp
string firstName = null;
string lastName = null;
var stub = new StubIPhoneBook
{
GetContactPhoneNumber_String_String = (fn, ln) =>
{
firstName = fn;
lastName = ln;
return 6041234567;
}
};
ClassUnderTest obj = new ClassUnderTest(stub);
Assert.AreEqual(expectedValue, obj.Foo());
// parameters verification
Assert.AreEqual("John", firstName);
Assert.AreEqual("Smith", lastName);
```
## Stubbing properties
```csharp
long myNumber = 6041234567;
var stub = new StubIPhoneBook
{
MyNumber_Get = () => myNumber,
MyNumber_Set = num =>
{
myNumber = num;
}
};
```
## Stubbing events
```csharp
var stub = new StubIPhoneBook();
// Pass the stub to the code under test
var obj = new ClassUnderTest(stub);
// Raise the event
stub.PhoneNumberChanged_Raise(stub, 55);
// Verify the state of obj to ensure that it has reacted to the event
```
## Stubbing a sequence of calls
In some cases, it might be useful to have a stub behave differently when it's called several times. SimpleStubs offers supports for stubbing a sequence of calls.
```csharp
// Define the sequence first
var sequence = StubsUtils.Sequence<Func<string, string, int>>()
.Once((p1, p2) => { throw new Exception(); }) // first call will throw an exception
.Repeat((p1, p2) => 11122233, 3) // next three calls will return 11122233
.Forever((p1, p2) => 22233556); // any subsequent call will return 22233556
var stub = new StubIPhoneBook
{
// Get the next element from the sequence every time the method is called and invoke it
GetContactPhoneNumber_String_String = (p1, p2) => sequence.Next(p1, p2)
};
// you can also verify how many times the sequence was called
Assert.AreEqual(5, sequence.CallCount);
```
## Full Example
Let's look at how we can unit test the following class (`LocationManager`) using SimpleStubs.
```csharp
using System.Threading.Tasks;
namespace HelloApp
{
public class LocationManager
{
private readonly ILocationService _locationService;
public LocationManager(ILocationService locationService)
{
_locationService = locationService;
}
/// <returns>Current Location or null if the location could not be retrieved</returns>
public async Task<Location> GetCurrentLocation()
{
try
{
string location = await _locationService.GetLocation();
var ss = location.Split('/');
return new Location(ss[0], ss[1]);
}
catch (LocationServiceUnavailableException)
{
return null;
}
}
/// <returns>The current country code (e.g. US, CA) or null if the country code could not be retrieved</returns>
public async Task<string> GetCurrentCountryCode()
{
try
{
Location location = await GetCurrentLocation();
string loc = $"{location.Country}/{location.City}";
return await _locationService.GetCountryCode(loc);
}
catch (LocationServiceUnavailableException)
{
return null;
}
}
}
}
```
The `ILocationService` interface is as follows:
```csharp
using System;
using System.Threading.Tasks;
namespace HelloApp
{
public interface ILocationService
{
/// <returns>
/// the location in the format Country/City
/// </returns>
/// <exception cref="LocationServiceUnavailableException"></exception>
Task<string> GetLocation();
/// <returns>the country code of the given location</returns>
/// <exception cref="LocationServiceUnavailableException"></exception>
Task<string> GetCountryCode(string location);
}
}
```
SimpleStubs will automatically generate a stub for `ILocationService` called StubILocationService. The following tests show how the stub can be used to unit test the `LocationManager` class:
```csharp
[TestMethod]
public async Task TestGetCurrentLocation()
{
StubILocationService locationServiceStub = new StubILocationService
{
GetLocation = () => Task.FromResult("Canada/Vancouver")
};
LocationManager locationManager = new LocationManager(locationServiceStub);
Location location = await locationManager.GetCurrentLocation();
Assert.AreEqual("Canada", location.Country);
Assert.AreEqual("Vancouver", location.City);
Assert.AreEqual(1, locationServiceStub.ILocationService_GetLocation_CallCount);
}
[TestMethod]
public async Task TestThatGetCurrentLocationReturnsNullIfLocationServiceIsUnavailable()
{
StubILocationService locationServiceStub = new StubILocationService
{
GetLocation = () =>
{
throw new LocationServiceUnavailableException();
}
};
LocationManager locationManager = new LocationManager(locationServiceStub);
Assert.IsNull(await locationManager.GetCurrentLocation());
Assert.AreEqual(1, locationServiceStub.ILocationService_GetLocation_CallCount);
}
[TestMethod]
public async Task TestGetCurrentCountryCode()
{
StubILocationService locationServiceStub = new StubILocationService
{
GetLocation = () => Task.FromResult("Canada/Vancouver"),
GetCountryCode_String = location => Task.FromResult("CA")
};
LocationManager locationManager = new LocationManager(locationServiceStub);
Assert.AreEqual("CA", await locationManager.GetCurrentCountryCode());
Assert.AreEqual(1, locationServiceStub.ILocationService_GetCountryCode_String_CallCount);
}
```
## Configuration
SimpleStubs also supports an optional configuration file that can be added to the root of your test project. The configuration file (named `SimpleStubs.json`) has the following structure:
```json
{
"IgnoredProjects": [
"IgnoredProject1",
"IgnoredProject2"
],
"IgnoredInterfaces": [
"MyNamespace.IFooInterface",
"MyNamespace.IBarInterface"
],
"StubInternalInterfaces": false
}
```
The configuration file allows you to instruct SimpleStubs to omit creating stubs for a given project or interface.
**Note** that this very useful to exclude interfaces that are causing SimpleStubs to generate stubs that don't compile (this can happen in some edge cases). If you encounter such a case, exclude the interface in question and report the problem so we can fix it.
It's also possible to instruct SimpleStubs to create stubs for internal interfaces (by default only public interfaces are stubbed) as shown in the configuration sample above.
## Current limitations
* Methods signatures with pointers are not supported.
* Generic methods are not supported (but generic interfaces are).
* Only interfaces are stubbed.
## What if some stubs don't compile?
Exclude the interface that is causing the problem (using the `SimpleStubs.json` configuration file) and report the problem.

13
LICENSE Normal file
Просмотреть файл

@ -0,0 +1,13 @@
SimpleStubs
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

1
NuGet/NuGetPack.bat Normal file
Просмотреть файл

@ -0,0 +1 @@
nuget pack SimpleStubs.nuspec

7
NuGet/SimpleStubs.json Normal file
Просмотреть файл

@ -0,0 +1,7 @@
{
"IgnoredProjects": [
],
"IgnoredInterfaces": [
],
"StubInternalInterfaces": false
}

51
NuGet/SimpleStubs.nuspec Normal file
Просмотреть файл

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Etg.SimpleStubs</id>
<version>1.0.3</version>
<title>SimpleStubs mocking framework</title>
<authors>Microsoft Studios (BigPark)</authors>
<owners>Microsoft Studios (BigPark)</owners>
<licenseUrl>https://opensource.org/licenses/MIT</licenseUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>SimpleStubs is a simple mocking framework that supports Universal Windows Platform (UWP), .NET Core and .NET framework. SimpleStubs is currently developed and maintained by Microsoft BigPark Studios in Vancouver.</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2016</copyright>
</metadata>
<files>
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\uap10.0" />
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\netcore45" />
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\netcore50" />
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\dnxcore50" />
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\dotnet" />
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\net46" />
<file src="..\src\SimpleStubs\bin\Release\ETG.SimpleStubs.dll" target="lib\dotnet50" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Etg.SimpleStubs.CodeGen.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.Build.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.Build.Engine.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.Build.Framework.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.Build.Tasks.Core.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.Build.Utilities.Core.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.CodeAnalysis.CSharp.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.CodeAnalysis.CSharp.Workspaces.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.CodeAnalysis.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.CodeAnalysis.Workspaces.Desktop.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Microsoft.CodeAnalysis.Workspaces.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Collections.Immutable.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Composition.AttributedModel.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Composition.Convention.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Composition.Hosting.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Composition.Runtime.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Composition.TypedParts.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\System.Reflection.Metadata.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Newtonsoft.Json.dll" target="tools" />
<file src="..\src\SimpleStubs.CodeGen\bin\Release\Autofac.dll" target="tools" />
<file src="..\Targets\Etg.SimpleStubs.targets" target="build" />
<file src="SimpleStubs.generated.cs" target="content\Properties\SimpleStubs.generated.cs" />
<file src="SimpleStubs.json" target="content\SimpleStubs.json" />
</files>
</package>

Просмотреть файл

@ -1,2 +1,20 @@
# SimpleStubs
SimpleStubs
=======
*SimpleStubs* is a simple mocking framework that supports Universal Windows Platform (UWP), .NET Core and .NET framework. SimpleStubs is currently developed and maintained by Microsoft BigPark Studios in Vancouver.
The framework can be installed to your test project using `Etg.SimpleStubs` NuGet package.
Please read the documentation below to learn more about how to install and use SimpleStubs.
Documentation
=======
* [Tutorial](Documentation/Tutorial.md).
Contribute!
=======
We welcome contributions of all sorts including pull requests, suggestions, documentation, etc. Please feel free to open an issue to discuss any matter.
License
=======
This project is licensed under the [MIT license](LICENSE).

Просмотреть файл

@ -0,0 +1,62 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloApp", "HelloApp\HelloApp.csproj", "{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloAppTest", "HelloAppTest\HelloAppTest.csproj", "{C19251DF-36F9-46C6-B02D-22DAF2F8197D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|ARM.ActiveCfg = Debug|ARM
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|ARM.Build.0 = Debug|ARM
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|x64.ActiveCfg = Debug|x64
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|x64.Build.0 = Debug|x64
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|x86.ActiveCfg = Debug|x86
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Debug|x86.Build.0 = Debug|x86
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|Any CPU.Build.0 = Release|Any CPU
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|ARM.ActiveCfg = Release|ARM
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|ARM.Build.0 = Release|ARM
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|x64.ActiveCfg = Release|x64
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|x64.Build.0 = Release|x64
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|x86.ActiveCfg = Release|x86
{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}.Release|x86.Build.0 = Release|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|Any CPU.ActiveCfg = Debug|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|ARM.ActiveCfg = Debug|ARM
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|ARM.Build.0 = Debug|ARM
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|ARM.Deploy.0 = Debug|ARM
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|x64.ActiveCfg = Debug|x64
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|x64.Build.0 = Debug|x64
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|x64.Deploy.0 = Debug|x64
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|x86.ActiveCfg = Debug|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|x86.Build.0 = Debug|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Debug|x86.Deploy.0 = Debug|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|Any CPU.ActiveCfg = Release|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|ARM.ActiveCfg = Release|ARM
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|ARM.Build.0 = Release|ARM
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|ARM.Deploy.0 = Release|ARM
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|x64.ActiveCfg = Release|x64
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|x64.Build.0 = Release|x64
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|x64.Deploy.0 = Release|x64
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|x86.ActiveCfg = Release|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|x86.Build.0 = Release|x86
{C19251DF-36F9-46C6-B02D-22DAF2F8197D}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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>{51FAEF20-C80E-4A15-BC77-1375CA9F7DA8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>HelloApp</RootNamespace>
<AssemblyName>HelloApp</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10586.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="LocationManager.cs" />
<Compile Include="ILocationService.cs" />
<Compile Include="Location.cs" />
<Compile Include="LocationServiceUnavailableException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Content Include="Properties\HelloApp.rd.xml" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,20 @@
using System.Threading.Tasks;
namespace HelloApp
{
public interface ILocationService
{
/// <summary>
///
/// </summary>
/// <returns>
/// the location in the format Country/City
/// </returns>
/// <exception cref="LocationServiceUnavailableException"></exception>
Task<string> GetLocation();
/// <returns>the country code of the given location</returns>
/// <exception cref="LocationServiceUnavailableException"></exception>
Task<string> GetCountryCode(string location);
}
}

Просмотреть файл

@ -0,0 +1,45 @@
namespace HelloApp
{
public class Location
{
protected bool Equals(Location other)
{
return string.Equals(Country, other.Country) && string.Equals(City, other.City);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Location) obj);
}
public override int GetHashCode()
{
unchecked
{
return ((Country != null ? Country.GetHashCode() : 0)*397) ^ (City != null ? City.GetHashCode() : 0);
}
}
public static bool operator ==(Location left, Location right)
{
return Equals(left, right);
}
public static bool operator !=(Location left, Location right)
{
return !Equals(left, right);
}
public Location(string country, string city)
{
Country = country;
City = city;
}
public string Country { get; }
public string City { get; }
}
}

Просмотреть файл

@ -0,0 +1,46 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Windows.Devices.PointOfService;
namespace HelloApp
{
public class LocationManager
{
private readonly ILocationService _locationService;
public LocationManager(ILocationService locationService)
{
_locationService = locationService;
}
/// <returns>Current Location or null if the location could not be retrieved</returns>
public async Task<Location> GetCurrentLocation()
{
try
{
string location = await _locationService.GetLocation();
var ss = location.Split('/');
return new Location(ss[0], ss[1]);
}
catch (LocationServiceUnavailableException)
{
return null;
}
}
/// <returns>The current country code (e.g. US, CA) or null if the country code could not be retrieved</returns>
public async Task<string> GetCurrentCountryCode()
{
try
{
Location location = await GetCurrentLocation();
string loc = $"{location.Country}/{location.City}";
return await _locationService.GetCountryCode(loc);
}
catch (LocationServiceUnavailableException)
{
return null;
}
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
using System;
namespace HelloApp
{
public class LocationServiceUnavailableException : Exception
{
}
}

Просмотреть файл

@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("HelloApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HelloApp")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains Runtime Directives, specifications about types your application accesses
through reflection and other dynamic code patterns. Runtime Directives are used to control the
.NET Native optimizer and ensure that it does not remove code accessed by your library. If your
library does not do any reflection, then you generally do not need to edit this file. However,
if your library reflects over types, especially types passed to it or derived from its types,
then you should write Runtime Directives.
The most common use of reflection in libraries is to discover information about types passed
to the library. Runtime Directives have three ways to express requirements on types passed to
your library.
1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
Use these directives to reflect over types passed as a parameter.
2. SubTypes
Use a SubTypes directive to reflect over types derived from another type.
3. AttributeImplies
Use an AttributeImplies directive to indicate that your library needs to reflect over
types or methods decorated with an attribute.
For more information on writing Runtime Directives for libraries, please visit
http://go.microsoft.com/fwlink/?LinkID=391919
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="HelloApp">
<!-- add directives for your library here -->
</Library>
</Directives>

Просмотреть файл

@ -0,0 +1,16 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

Двоичные данные
Samples/HelloApp/HelloAppTest/Assets/LockScreenLogo.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
Samples/HelloApp/HelloAppTest/Assets/SplashScreen.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.5 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.9 KiB

Двоичные данные
Samples/HelloApp/HelloAppTest/Assets/Square44x44Logo.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
Samples/HelloApp/HelloAppTest/Assets/StoreLogo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
Samples/HelloApp/HelloAppTest/Assets/Wide310x150Logo.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Просмотреть файл

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{C19251DF-36F9-46C6-B02D-22DAF2F8197D}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>HelloAppTest</RootNamespace>
<AssemblyName>HelloAppTest</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10586.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PackageCertificateKeyFile>HelloAppTest_TemporaryKey.pfx</PackageCertificateKeyFile>
<UnitTestPlatformVersion Condition="'$(UnitTestPlatformVersion)' == ''">14.0</UnitTestPlatformVersion>
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<ItemGroup>
<!--A reference to the entire .Net Framework and Windows SDK are automatically included-->
<None Include="project.json" />
<SDKReference Include="MSTestFramework.Universal, Version=$(UnitTestPlatformVersion)" />
<SDKReference Include="TestPlatform.Universal, Version=$(UnitTestPlatformVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\SimpleStubs.cs" />
<Compile Include="UnitTestApp.xaml.cs">
<DependentUpon>UnitTestApp.xaml</DependentUpon>
</Compile>
<Compile Include="LocationManagerTest.cs" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="UnitTestApp.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="HelloAppTest_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<Content Include="Properties\UnitTestApp.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\HelloApp\HelloApp.csproj">
<Project>{51faef20-c80e-4a15-bc77-1375ca9f7da8}</Project>
<Name>HelloApp</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(NuGetPackageRoot)' == ''">
<NuGetPackageRoot>$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
</PropertyGroup>
<ImportGroup>
<Import Project="$(NuGetPackageRoot)\Etg.SimpleStubs\0.0.1-beta\build\Etg.SimpleStubs.targets" Condition="Exists('$(NuGetPackageRoot)\Etg.SimpleStubs\0.0.1-beta\build\Etg.SimpleStubs.targets')" />
</ImportGroup>
</Project>

Просмотреть файл

@ -0,0 +1,56 @@
using System.Threading.Tasks;
using HelloApp;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
namespace HelloAppTest
{
[TestClass]
public class LocationManagerTest
{
[TestMethod]
public async Task TestGetCurrentLocation()
{
StubILocationService locationServiceStub = new StubILocationService
{
ILocationService_GetLocation = () => Task.FromResult("Canada/Vancouver")
};
LocationManager locationManager = new LocationManager(locationServiceStub);
Location location = await locationManager.GetCurrentLocation();
Assert.AreEqual("Canada", location.Country);
Assert.AreEqual("Vancouver", location.City);
Assert.AreEqual(1, locationServiceStub.ILocationService_GetLocation_CallCount);
}
[TestMethod]
public async Task TestThatGetCurrentLocationReturnsNullIfLocationServiceIsUnavailable()
{
StubILocationService locationServiceStub = new StubILocationService
{
ILocationService_GetLocation = () =>
{
throw new LocationServiceUnavailableException();
}
};
LocationManager locationManager = new LocationManager(locationServiceStub);
Assert.IsNull(await locationManager.GetCurrentLocation());
Assert.AreEqual(1, locationServiceStub.ILocationService_GetLocation_CallCount);
}
[TestMethod]
public async Task TestGetCurrentCountryCode()
{
StubILocationService locationServiceStub = new StubILocationService
{
ILocationService_GetLocation = () => Task.FromResult("Canada/Vancouver"),
ILocationService_GetCountryCode_String = location => Task.FromResult("CA")
};
LocationManager locationManager = new LocationManager(locationServiceStub);
Assert.AreEqual("CA", await locationManager.GetCurrentCountryCode());
Assert.AreEqual(1, locationServiceStub.ILocationService_GetCountryCode_String_CallCount);
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity Name="7381d360-7032-4a64-a385-1bd0786ce5fb"
Publisher="CN=nbilal"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="7381d360-7032-4a64-a385-1bd0786ce5fb" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>HelloAppTest</DisplayName>
<PublisherDisplayName>nbilal</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="vstest.executionengine.universal.App"
Executable="$targetnametoken$.exe"
EntryPoint="HelloAppTest.App">
<uap:VisualElements
DisplayName="HelloAppTest"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="HelloAppTest"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>

Просмотреть файл

@ -0,0 +1,30 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("HelloAppTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HelloAppTest")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyMetadata("TargetPlatform","UAP")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,31 @@
using System.Threading.Tasks;
namespace HelloApp
{
public class StubILocationService : ILocationService
{
global::System.Threading.Tasks.Task<string> global::HelloApp.ILocationService.GetLocation()
{
++ILocationService_GetLocation_CallCount;
return ILocationService_GetLocation();
}
public delegate global::System.Threading.Tasks.Task<string> ILocationService_GetLocation_Delegate();
public ILocationService_GetLocation_Delegate ILocationService_GetLocation;
public int ILocationService_GetLocation_CallCount { get; private set; } = 0;
global::System.Threading.Tasks.Task<string> global::HelloApp.ILocationService.GetCountryCode(string location)
{
++ILocationService_GetCountryCode_String_CallCount;
return ILocationService_GetCountryCode_String(location);
}
public delegate global::System.Threading.Tasks.Task<string> ILocationService_GetCountryCode_String_Delegate(string location);
public ILocationService_GetCountryCode_String_Delegate ILocationService_GetCountryCode_String;
public int ILocationService_GetCountryCode_String_CallCount { get; private set; } = 0;
}
}

Просмотреть файл

@ -0,0 +1,30 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>

Просмотреть файл

@ -0,0 +1,8 @@
<Application
x:Class="HelloAppTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloAppTest"
RequestedTheme="Light">
</Application>

Просмотреть файл

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace HelloAppTest
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
// Ensure the current window is active
Window.Current.Activate();
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments);
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
{
"dependencies": {
"Etg.SimpleStubs": "0.0.1-beta",
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

94
SimpleStubs.sln Normal file
Просмотреть файл

@ -0,0 +1,94 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStubs.CodeGen", "src\SimpleStubs.CodeGen\SimpleStubs.CodeGen.csproj", "{3E9C520A-94CF-46D0-864B-4293D439C92A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStubs", "src\SimpleStubs\SimpleStubs.csproj", "{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClassLibrary", "test\TestClassLibrary\TestClassLibrary.csproj", "{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClassLibraryTest", "test\TestClassLibraryTest\TestClassLibraryTest.csproj", "{CB81F60F-1374-4B46-BB64-D848B5103A58}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|ARM.Build.0 = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|x64.ActiveCfg = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|x64.Build.0 = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|x86.ActiveCfg = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Debug|x86.Build.0 = Debug|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|Any CPU.Build.0 = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|ARM.ActiveCfg = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|ARM.Build.0 = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|x64.ActiveCfg = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|x64.Build.0 = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|x86.ActiveCfg = Release|Any CPU
{3E9C520A-94CF-46D0-864B-4293D439C92A}.Release|x86.Build.0 = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|ARM.Build.0 = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|x64.ActiveCfg = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|x64.Build.0 = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|x86.ActiveCfg = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Debug|x86.Build.0 = Debug|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|Any CPU.Build.0 = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|ARM.ActiveCfg = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|ARM.Build.0 = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|x64.ActiveCfg = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|x64.Build.0 = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|x86.ActiveCfg = Release|Any CPU
{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}.Release|x86.Build.0 = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|ARM.Build.0 = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|x64.ActiveCfg = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|x64.Build.0 = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|x86.ActiveCfg = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Debug|x86.Build.0 = Debug|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|Any CPU.Build.0 = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|ARM.ActiveCfg = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|ARM.Build.0 = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|x64.ActiveCfg = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|x64.Build.0 = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|x86.ActiveCfg = Release|Any CPU
{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}.Release|x86.Build.0 = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|ARM.ActiveCfg = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|ARM.Build.0 = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|x64.ActiveCfg = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|x64.Build.0 = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|x86.ActiveCfg = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Debug|x86.Build.0 = Debug|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|Any CPU.Build.0 = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|ARM.ActiveCfg = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|ARM.Build.0 = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|x64.ActiveCfg = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|x64.Build.0 = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|x86.ActiveCfg = Release|Any CPU
{CB81F60F-1374-4B46-BB64-D848B5103A58}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,11 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="Etg.SimpleStubs.CodeGen.Tasks.GenerateStubsTask" AssemblyFile="$(MSBuildThisFileDirectory)..\tools\Etg.SimpleStubs.CodeGen.dll" />
<PropertyGroup>
<SimpleStubsCodeGenBeforeTargets>BeforeBuild</SimpleStubsCodeGenBeforeTargets>
</PropertyGroup>
<Target Name="SimpleStubsCodeGen" BeforeTargets="$(SimpleStubsCodeGenBeforeTargets)">
<GenerateStubsTask ProjectPath="$(ProjectDir)$(ProjectName)$(ProjectExt)" OutputPath="$(ProjectDir)Properties\SimpleStubs.generated.cs" />
</Target>
</Project>

7
nuget.config Normal file
Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/"/>
<add key="nuget (SimpleStubs)" value="NuGet"/>
</packageSources>
</configuration>

Просмотреть файл

@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Etg.SimpleStubs.CodeGen.Utils;
namespace Etg.SimpleStubs.CodeGen
{
using SF = SyntaxFactory;
class EventStubber : IMethodStubber
{
public ClassDeclarationSyntax StubMethod(ClassDeclarationSyntax classDclr, IMethodSymbol methodSymbol, INamedTypeSymbol stubbedInterface)
{
// only handle EventAdd and ignore EventRemove because we only need to stub the event once
if (!methodSymbol.IsEventAdd())
{
return classDclr;
}
// add the event implementation to the stub
IEventSymbol eventSymbol = (IEventSymbol)methodSymbol.AssociatedSymbol;
EventFieldDeclarationSyntax eventDclr = ToEventDclr(eventSymbol);
classDclr = classDclr.AddMembers(eventDclr);
string eventName = eventSymbol.Name;
ParameterSyntax[] parameters = GetEventParameters(eventSymbol);
string onEventArgs = "sender";
string eventTriggerArgs = "sender";
if (parameters.Count() == 2)
{
onEventArgs += ", args";
eventTriggerArgs += ", args";
}
else if (parameters.Count() == 1)
{
onEventArgs += ", null";
}
string eventType = GetEventType(eventSymbol);
string onEventMethodName = "On_" + eventName;
// Create OnEvent method
MethodDeclarationSyntax onEventMethodDclr = SF.MethodDeclaration(SF.ParseTypeName("void"), onEventMethodName)
.AddModifiers(SF.Token(SyntaxKind.ProtectedKeyword))
.AddParameterListParameters(parameters)
.WithBody(SF.Block(
SF.ParseStatement($"{eventType} handler = {eventName};\n"),
SF.ParseStatement($"if (handler != null) {{ handler({onEventArgs}); }}\n")
));
classDclr = classDclr.AddMembers(onEventMethodDclr);
// Create event trigger method
string eventTriggerMethodName = eventName + "_Raise";
MethodDeclarationSyntax eventTriggerMethod = SF.MethodDeclaration(SF.ParseTypeName("void"), eventTriggerMethodName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(parameters)
.WithBody(SF.Block(
SF.ParseStatement($"{onEventMethodName}({eventTriggerArgs});\n")
));
classDclr = classDclr.AddMembers(eventTriggerMethod);
return classDclr;
}
private static ParameterSyntax[] GetEventParameters(IEventSymbol eventSymbol)
{
List<ParameterSyntax> parameters = new List<ParameterSyntax>
{
SF.Parameter(SF.Identifier("sender")).WithType(SF.ParseTypeName("object"))
};
INamedTypeSymbol type = (INamedTypeSymbol)(eventSymbol.Type);
if (type.TypeArguments.Any())
{
parameters.Add(SF.Parameter(SF.Identifier("args")).WithType(SF.ParseTypeName(type.TypeArguments[0].Name)));
}
return parameters.ToArray();
}
private static EventFieldDeclarationSyntax ToEventDclr(IEventSymbol eventSymbol)
{
string eventName = eventSymbol.Name;
string eventType = GetEventType(eventSymbol);
EventFieldDeclarationSyntax eventDclr = SF.EventFieldDeclaration(
SF.VariableDeclaration(SF.IdentifierName(eventType),
SF.SeparatedList(new[] { SF.VariableDeclarator(eventName) }))).AddModifiers(SF.Token(SyntaxKind.PublicKeyword));
return eventDclr;
}
private static string GetEventType(IEventSymbol eventSymbol)
{
return eventSymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Etg.SimpleStubs.CodeGen
{
interface IInterfaceStubber
{
CompilationUnitSyntax StubInterface(CompilationUnitSyntax cu, InterfaceDeclarationSyntax interfaceDclr, SemanticModel semanticModel);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Etg.SimpleStubs.CodeGen
{
interface IMethodStubber
{
ClassDeclarationSyntax StubMethod(ClassDeclarationSyntax classDclr, IMethodSymbol methodSymbol, INamedTypeSymbol stubbedInterface);
}
}

Просмотреть файл

@ -0,0 +1,11 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Etg.SimpleStubs.CodeGen.CodeGen
{
interface IProjectStubber
{
Task<StubProjectResult> StubProject(Project project, CompilationUnitSyntax cu);
}
}

Просмотреть файл

@ -0,0 +1,86 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using System.Collections.Generic;
using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using Etg.SimpleStubs.CodeGen.Utils;
namespace Etg.SimpleStubs.CodeGen
{
class InterfaceStubber : IInterfaceStubber
{
private readonly IEnumerable<IMethodStubber> _methodStubbers;
public InterfaceStubber(IEnumerable<IMethodStubber> methodStubbers)
{
_methodStubbers = new List<IMethodStubber>(methodStubbers);
}
public CompilationUnitSyntax StubInterface(CompilationUnitSyntax cu, InterfaceDeclarationSyntax interfaceDclr,
SemanticModel semanticModel)
{
INamedTypeSymbol interfaceType = semanticModel.GetDeclaredSymbol(interfaceDclr);
NamespaceDeclarationSyntax namespaceNode = GetNamespaceNode(interfaceDclr);
string interfaceName = interfaceType.GetGenericName();
string stubName = NamingUtils.GetStubName(interfaceName);
ClassDeclarationSyntax classDclr = SF.ClassDeclaration(SF.Identifier(stubName))
.AddModifiers(SF.Token(RoslynUtils.GetVisibilityKeyword(interfaceType))
//,SF.Token(SyntaxKind.PartialKeyword)
)
.WithBaseList(RoslynUtils.BaseList(interfaceName))
.AddAttributeLists(AttributeListList(Attribute("CompilerGenerated")).ToArray());
List<IMethodSymbol> methodsToStub = RoslynUtils.GetAllMethods(interfaceType);
foreach (IMethodSymbol methodSymbol in methodsToStub)
{
foreach(IMethodStubber methodStubber in _methodStubbers)
{
classDclr = methodStubber.StubMethod(classDclr, methodSymbol, interfaceType);
}
}
string fullNameSpace = semanticModel.GetDeclaredSymbol(namespaceNode).ToString();
NamespaceDeclarationSyntax namespaceDclr = SF.NamespaceDeclaration(SF.IdentifierName(fullNameSpace))
.WithUsings(namespaceNode.Usings);
namespaceDclr = namespaceDclr.AddMembers(classDclr);
cu = cu.AddMembers(namespaceDclr);
return cu;
}
private static NamespaceDeclarationSyntax GetNamespaceNode(InterfaceDeclarationSyntax interfaceNode)
{
var namespaceNode = interfaceNode.Parent as NamespaceDeclarationSyntax;
if (namespaceNode == null)
{
throw new Exception("A grain interface must be declared inside a namespace");
}
return namespaceNode;
}
private static SyntaxList<AttributeListSyntax> AttributeListList(params AttributeSyntax[] attributes)
{
var list = new SyntaxList<AttributeListSyntax>();
foreach (AttributeSyntax attributeSyntax in attributes)
{
list = list.Add(AttributeList(attributeSyntax));
}
return list;
}
private static AttributeListSyntax AttributeList(params AttributeSyntax[] attributes)
{
SeparatedSyntaxList<AttributeSyntax> separatedList = SF.SeparatedList<AttributeSyntax>();
foreach (var attributeSyntax in attributes)
{
separatedList = separatedList.Add(attributeSyntax);
}
return SF.AttributeList(separatedList);
}
private static AttributeSyntax Attribute(string attributeName)
{
return SF.Attribute(SF.IdentifierName(attributeName));
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
using Etg.SimpleStubs.CodeGen.Utils;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Etg.SimpleStubs.CodeGen
{
class OrdinaryMethodStubber : IMethodStubber
{
public ClassDeclarationSyntax StubMethod(ClassDeclarationSyntax classDclr, IMethodSymbol methodSymbol, INamedTypeSymbol stubbedInterface)
{
if(!methodSymbol.IsOrdinaryMethod())
{
return classDclr;
}
MethodDeclarationSyntax methodDclr = SF.MethodDeclaration(
SF.ParseTypeName(methodSymbol.ReturnType.GetFullyQualifiedName()), methodSymbol.GetGenericName());
methodDclr = methodDclr.WithParameterList(methodDclr.ParameterList.AddParameters(
RoslynUtils.GetMethodParameterSyntaxList(methodSymbol).ToArray()));
methodDclr = methodDclr.WithSemicolonToken(SF.Token(SyntaxKind.None))
.WithExplicitInterfaceSpecifier(
SF.ExplicitInterfaceSpecifier(
SF.IdentifierName(methodSymbol.GetContainingInterfaceGenericQualifiedName())));
if (methodSymbol.IsGenericMethod)
{
StatementSyntax stmtSyntax;
if (methodSymbol.ReturnsVoid)
{
stmtSyntax = SF.ParseStatement("\n");
}
else
{
stmtSyntax = SF.ParseStatement($"return default({methodSymbol.ReturnType.GetFullyQualifiedName()});\n");
}
classDclr = classDclr.AddMembers(methodDclr.WithBody(SF.Block(stmtSyntax)));
}
else
{
string delegatePropertyName = NamingUtils.GetDelegatePropertyName(methodSymbol, stubbedInterface);
string callDelegateStmt = $"{delegatePropertyName}({string.Join(", ", methodSymbol.Parameters.Select(p => p.Name))});\n";
if (!methodSymbol.ReturnsVoid)
{
callDelegateStmt = callDelegateStmt.Insert(0, "return ");
}
classDclr = classDclr.AddMembers(
methodDclr.WithBody(SF.Block(SF.ParseStatement(callDelegateStmt))));
}
return classDclr;
}
}
}

Просмотреть файл

@ -0,0 +1,73 @@
using Etg.SimpleStubs.CodeGen.Config;
using Etg.SimpleStubs.CodeGen.Utils;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Etg.SimpleStubs.CodeGen.CodeGen
{
class ProjectStubber : IProjectStubber
{
private readonly IInterfaceStubber _interfaceStubber;
private readonly SimpleStubsConfig _config;
public ProjectStubber(IInterfaceStubber interfaceStubber, SimpleStubsConfig config)
{
_interfaceStubber = interfaceStubber;
_config = config;
}
public async Task<StubProjectResult> StubProject(Project project, CompilationUnitSyntax cu)
{
var usings = new List<string>();
foreach (Document document in project.Documents)
{
SyntaxTree syntaxTree = await document.GetSyntaxTreeAsync();
SemanticModel semanticModel = await document.GetSemanticModelAsync();
IEnumerable<InterfaceDeclarationSyntax> interfaces = syntaxTree.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>().Where(i => SatisfiesVisibilityConstraints(i));
if (!interfaces.Any())
{
continue;
}
foreach (var interfaceDclr in interfaces)
{
try
{
INamedTypeSymbol interfaceType = semanticModel.GetDeclaredSymbol(interfaceDclr);
if (!_config.IgnoredInterfaces.Contains(interfaceType.GetQualifiedName()))
{
LogWarningsIfAny(semanticModel);
cu = _interfaceStubber.StubInterface(cu, interfaceDclr, semanticModel);
}
}
catch (Exception e)
{
Trace.TraceError($"Could not generate stubs for interface {interfaceDclr}, Exception: {e}");
}
}
usings.AddRange(syntaxTree.GetCompilationUnitRoot().Usings.Select(@using => @using.Name.ToString()));
}
return new StubProjectResult(cu, usings);
}
private bool SatisfiesVisibilityConstraints(InterfaceDeclarationSyntax i)
{
return i.IsPublic() || (_config.StubInternalInterfaces && i.IsInternal());
}
private void LogWarningsIfAny(SemanticModel semanticModel)
{
foreach (var diagnostic in semanticModel.GetDiagnostics())
{
Trace.TraceInformation(diagnostic.ToString());
}
}
}
}

Просмотреть файл

@ -0,0 +1,69 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Etg.SimpleStubs.CodeGen.Utils;
namespace Etg.SimpleStubs.CodeGen
{
using Microsoft.CodeAnalysis.CSharp;
using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
class PropertyStubber : IMethodStubber
{
public ClassDeclarationSyntax StubMethod(ClassDeclarationSyntax classDclr, IMethodSymbol methodSymbol, INamedTypeSymbol stubbedInterface)
{
if (!methodSymbol.IsPropertyAccessor())
{
return classDclr;
}
string delegatePropertyName = NamingUtils.GetDelegatePropertyName(methodSymbol, stubbedInterface);
string propName = methodSymbol.AssociatedSymbol.Name;
string propType = ((IPropertySymbol)methodSymbol.AssociatedSymbol).Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var propDclr = GetPropDclr(classDclr, propName);
if (propDclr == null)
{
propDclr = SF.PropertyDeclaration(SF.ParseTypeName(propType), SF.Identifier(propName))
.WithExplicitInterfaceSpecifier(SF.ExplicitInterfaceSpecifier(
SF.IdentifierName(methodSymbol.GetContainingInterfaceGenericQualifiedName())));
}
if (methodSymbol.IsPropertyGetter())
{
var accessorDclr = SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, SF.Block(
SF.List(new[] {
SF.ReturnStatement(SF.IdentifierName(delegatePropertyName + "()")) })));
propDclr = propDclr.AddAccessorListAccessors(accessorDclr);
}
else if (methodSymbol.IsPropertySetter())
{
var accessorDclr = SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration, SF.Block(
SF.List(new[] {
SF.ParseStatement($"{delegatePropertyName}(value);\n") })));
propDclr = propDclr.AddAccessorListAccessors(accessorDclr);
}
if (propDclr != null)
{
PropertyDeclarationSyntax existingPropDclr = GetPropDclr(classDclr, propName);
if (existingPropDclr != null)
{
classDclr = classDclr.ReplaceNode(existingPropDclr, propDclr);
}
else
{
classDclr = classDclr.AddMembers(propDclr);
}
}
return classDclr;
}
private static PropertyDeclarationSyntax GetPropDclr(ClassDeclarationSyntax classDclr, string propName)
{
return classDclr.DescendantNodes().OfType<PropertyDeclarationSyntax>().FirstOrDefault(p => p.Identifier.Text == propName);
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.Formatting;
using System.Threading.Tasks;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using Etg.SimpleStubs.CodeGen.Config;
using Etg.SimpleStubs.CodeGen.CodeGen;
namespace Etg.SimpleStubs.CodeGen
{
internal class SimpleStubsGenerator
{
IProjectStubber _projectStubber;
SimpleStubsConfig _config;
public SimpleStubsGenerator(IProjectStubber projectStubber, SimpleStubsConfig config)
{
_projectStubber = projectStubber;
_config = config;
}
public async Task<string> GenerateStubs(string testProjectPath)
{
MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Project currentProject = await workspace.OpenProjectAsync(testProjectPath);
if (currentProject == null)
{
throw new ArgumentException("Could not open the project located at " + testProjectPath);
}
CompilationUnitSyntax cu = SF.CompilationUnit();
var usings = new HashSet<string>();
usings.Add("System");
usings.Add("System.Runtime.CompilerServices");
foreach (ProjectReference projectRef in currentProject.ProjectReferences)
{
Project project = workspace.CurrentSolution.GetProject(projectRef.ProjectId);
if (_config.IgnoredProjects.Contains(project.Name))
{
continue;
}
var res = await _projectStubber.StubProject(project, cu);
cu = res.CompilationUnit;
usings.UnionWith(res.Usings);
}
cu = cu.AddUsings(usings.Select(@using => SF.UsingDirective(SF.IdentifierName(@using))).ToArray());
return Formatter.Format(cu, workspace).ToString();
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
namespace Etg.SimpleStubs.CodeGen.CodeGen
{
class StubProjectResult
{
public StubProjectResult(CompilationUnitSyntax cu, IEnumerable<string> usings)
{
CompilationUnit = cu;
Usings = usings;
}
public CompilationUnitSyntax CompilationUnit
{
get;
}
public IEnumerable<string> Usings
{
get;
}
}
}

Просмотреть файл

@ -0,0 +1,52 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Etg.SimpleStubs.CodeGen.Utils;
namespace Etg.SimpleStubs.CodeGen
{
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
class StubbingPropertiesGenerator : IMethodStubber
{
public ClassDeclarationSyntax StubMethod(ClassDeclarationSyntax classDclr, IMethodSymbol methodSymbol,
INamedTypeSymbol stubbedInterface)
{
if (methodSymbol.IsPropertyAccessor() || methodSymbol.IsOrdinaryMethod())
{
if (!methodSymbol.IsGenericMethod)
{
string delegatePropertyName = NamingUtils.GetDelegatePropertyName(methodSymbol, stubbedInterface);
string delegateTypeName = NamingUtils.GetDelegateTypeName(delegatePropertyName);
DelegateDeclarationSyntax delegateDclr = GenerateDelegateDclr(methodSymbol, delegateTypeName, stubbedInterface);
PropertyDeclarationSyntax propDclr = GenerateDelegatePropDclr(
delegatePropertyName, delegateTypeName, stubbedInterface);
classDclr = classDclr.AddMembers(delegateDclr, propDclr);
}
}
return classDclr;
}
private static PropertyDeclarationSyntax GenerateDelegatePropDclr(string delegatePropertyName,
string delegateName, INamedTypeSymbol stubbedInterface)
{
SyntaxKind visibility = RoslynUtils.GetVisibilityKeyword(stubbedInterface);
return SF.PropertyDeclaration(SF.ParseTypeName(delegateName), delegatePropertyName)
.AddModifiers(SF.Token(visibility)).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken));
}
private static DelegateDeclarationSyntax GenerateDelegateDclr(IMethodSymbol methodSymbol, string delegateName,
INamedTypeSymbol stubbedInterface)
{
SyntaxKind visibility = RoslynUtils.GetVisibilityKeyword(stubbedInterface);
List<ParameterSyntax> paramsSyntaxList = RoslynUtils.GetMethodParameterSyntaxList(methodSymbol);
return SF.DelegateDeclaration(SF.ParseTypeName(methodSymbol.ReturnType.GetFullyQualifiedName()), delegateName)
.AddModifiers(SF.Token(visibility)).AddParameterListParameters(paramsSyntaxList.ToArray());
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using System.IO;
namespace Etg.SimpleStubs.CodeGen.Config
{
class ConfigLoader
{
public SimpleStubsConfig LoadConfig(string configFilePath)
{
if (File.Exists(configFilePath))
{
return JsonConvert.DeserializeObject<SimpleStubsConfig>(File.ReadAllText(configFilePath));
}
return new SimpleStubsConfig(new string[]{}, new string[]{}, false);
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace Etg.SimpleStubs.CodeGen.Config
{
class SimpleStubsConfig
{
public SimpleStubsConfig(IEnumerable<string> ignoredProjects,
IEnumerable<string> ignoredInterfaces,
bool stubInternalInterfaces)
{
IgnoredProjects = new HashSet<string>(ignoredProjects);
IgnoredInterfaces = new HashSet<string>(ignoredInterfaces);
StubInternalInterfaces = stubInternalInterfaces;
}
public ISet<string> IgnoredProjects
{
get;
}
public ISet<string> IgnoredInterfaces
{
get;
}
public bool StubInternalInterfaces
{
get;
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
using Autofac;
using Etg.SimpleStubs.CodeGen.CodeGen;
using Etg.SimpleStubs.CodeGen.Config;
using System.IO;
namespace Etg.SimpleStubs.CodeGen.DI
{
class DiModule
{
private readonly IContainer _container;
public DiModule(string testProjectPath, string stubsFilePath)
{
_container = RegisterTypes(testProjectPath, stubsFilePath).Build();
}
public static ContainerBuilder RegisterTypes(string testProjectPath, string stubsFilePath)
{
ContainerBuilder cb = new ContainerBuilder();
string configFilePath = Path.Combine(Path.GetDirectoryName(testProjectPath), "SimpleStubs.json");
SimpleStubsConfig config = new ConfigLoader().LoadConfig(configFilePath);
cb.RegisterInstance(config);
cb.Register((c) =>
{
IInterfaceStubber interfaceStubber = new InterfaceStubber(
new IMethodStubber[] {
new OrdinaryMethodStubber(),
new EventStubber(),
new PropertyStubber(),
new StubbingPropertiesGenerator() });
return interfaceStubber;
}).As<IInterfaceStubber>().SingleInstance();
cb.RegisterType<ProjectStubber>().As<IProjectStubber>().SingleInstance();
cb.RegisterType<SimpleStubsGenerator>().AsSelf();
return cb;
}
public SimpleStubsGenerator StubsGenerator => _container.Resolve<SimpleStubsGenerator>();
}
}

Просмотреть файл

@ -0,0 +1,37 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SimpleStubs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Etg.SimpleStubs.CodeGen")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3e9c520a-94cf-46d0-864b-4293d439c92a")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.0.1.0")]
[assembly: InternalsVisibleTo("TestClassLibraryTest")]

Просмотреть файл

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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>{3E9C520A-94CF-46D0-864B-4293D439C92A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Etg.SimpleStubs.CodeGen</RootNamespace>
<AssemblyName>Etg.SimpleStubs.CodeGen</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Build.Framework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Build.Utilities.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.CodeAnalysis, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.Workspaces, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.37.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.AttributedModel, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.Convention, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.Hosting, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.Runtime, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.TypedParts, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Reflection.Metadata, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
</Reference>
<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" />
</ItemGroup>
<ItemGroup>
<Compile Include="CodeGen\IInterfaceStubber.cs" />
<Compile Include="CodeGen\InterfaceStubber.cs" />
<Compile Include="CodeGen\IProjectStubber.cs" />
<Compile Include="CodeGen\ProjectStubber.cs" />
<Compile Include="CodeGen\StubProjectResult.cs" />
<Compile Include="Config\SimpleStubsConfig.cs" />
<Compile Include="Config\ConfigLoader.cs" />
<Compile Include="DI\DiModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CodeGen\EventStubber.cs" />
<Compile Include="Tasks\GenerateStubsTask.cs" />
<Compile Include="CodeGen\IMethodStubber.cs" />
<Compile Include="CodeGen\OrdinaryMethodStubber.cs" />
<Compile Include="CodeGen\PropertyStubber.cs" />
<Compile Include="CodeGen\StubbingPropertiesGenerator.cs" />
<Compile Include="CodeGen\SimpleStubsGenerator.cs" />
<Compile Include="Utils\NamingUtils.cs" />
<Compile Include="Utils\RoslynExtensions.cs" />
<Compile Include="Utils\RoslynUtils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,58 @@
using Microsoft.Build.Framework;
using System;
using System.IO;
using Etg.SimpleStubs.CodeGen.DI;
namespace Etg.SimpleStubs.CodeGen.Tasks
{
/// <summary>
/// </summary>
public class GenerateStubsTask : Microsoft.Build.Utilities.AppDomainIsolatedTask
{
[Required]
public string OutputPath
{
get;
set;
}
[Required]
public string ProjectPath
{
get;
set;
}
public override bool Execute()
{
try
{
LogMessage("Generating stubs");
DiModule diModule = new DiModule(ProjectPath, OutputPath);
File.WriteAllText(OutputPath, diModule.StubsGenerator.GenerateStubs(ProjectPath).Result);
return true;
}
catch (Exception e)
{
LogMessage(e.ToString());
}
return false;
}
private void LogMessage(string message)
{
Log.LogMessage(MessageImportance.High, DecorateMessage(message));
}
private static string DecorateMessage(string message)
{
return "SimpleStubs: " + message;
}
private void LogWarning(string message)
{
Log.LogWarning(DecorateMessage(message));
}
}
}

Просмотреть файл

@ -0,0 +1,82 @@
using Microsoft.CodeAnalysis;
using System.Linq;
using System.Text;
namespace Etg.SimpleStubs.CodeGen.Utils
{
class NamingUtils
{
public string GetInterfaceStubName(string interfaceName)
{
return "Stub" + interfaceName;
}
public static string GetDelegatePropertyName(IMethodSymbol methodSymbol, INamedTypeSymbol targetInterface)
{
string methodName = methodSymbol.Name;
if (methodSymbol.IsPropertyGetter())
{
methodName = methodName.Substring(4) + "_Get";
}
else if (methodSymbol.IsPropertySetter())
{
methodName = methodName.Substring(4) + "_Set";
}
// only prefix inherited members
if (targetInterface.GetGenericName() != methodSymbol.ContainingSymbol.GetGenericName())
{
methodName = SerializeName(methodSymbol.ContainingSymbol) + "_" + methodName;
}
if(methodSymbol.IsOrdinaryMethod())
{
if (methodSymbol.Parameters.Any())
{
methodName = methodName + "_" + string.Join("_", methodSymbol.Parameters.Select(SerializeName));
}
}
return methodName;
}
public static string GetDelegateTypeName(string delegatePropertyName)
{
return delegatePropertyName + "_Delegate";
}
public static string SerializeName(ISymbol param)
{
StringBuilder sb = new StringBuilder();
foreach (var part in param.ToDisplayParts(SymbolDisplayFormat.MinimallyQualifiedFormat))
{
switch (part.ToString())
{
case "<":
sb.Append("Of");
break;
case ">":
break;
case "]":
break;
case "[":
sb.Append("Array");
break;
default:
if (part.Symbol != null && part.Kind != SymbolDisplayPartKind.ParameterName)
{
sb.Append(part.Symbol.Name);
}
break;
}
}
return sb.ToString();
}
public static string GetStubName(string interfaceName)
{
return "Stub" + interfaceName;
}
}
}

Просмотреть файл

@ -0,0 +1,102 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
namespace Etg.SimpleStubs.CodeGen.Utils
{
static class RoslynExtensions
{
public static SymbolDisplayFormat QualifiedFormat = new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces);
public static bool IsEvent(this IMethodSymbol methodSymbol)
{
return methodSymbol.IsEventAdd() || methodSymbol.IsEventRemove();
}
public static bool IsEventAdd(this IMethodSymbol methodSymbol)
{
return methodSymbol.MethodKind == MethodKind.EventAdd;
}
public static bool IsEventRemove(this IMethodSymbol methodSymbol)
{
return methodSymbol.MethodKind == MethodKind.EventRemove;
}
public static bool IsPropertyAccessor(this IMethodSymbol methodSymbol)
{
return methodSymbol.IsPropertyGetter() || methodSymbol.IsPropertySetter();
}
public static bool IsPropertySetter(this IMethodSymbol methodSymbol)
{
return methodSymbol.MethodKind == MethodKind.PropertySet;
}
public static bool IsPropertyGetter(this IMethodSymbol methodSymbol)
{
return methodSymbol.MethodKind == MethodKind.PropertyGet;
}
public static string GetGenericName(this IMethodSymbol methodSymbol)
{
string name = methodSymbol.Name;
if (methodSymbol.IsGenericMethod)
{
name = $"{name}<{string.Join(",", methodSymbol.TypeParameters.Select(p => p.Name))}>";
}
return name;
}
public static string GetContainingInterfaceGenericQualifiedName(this IMethodSymbol methodSymbol)
{
return methodSymbol.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
}
public static string GetGenericName(this ISymbol namedType)
{
return namedType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
}
public static string GetFullyQualifiedName(this ITypeSymbol symbol)
{
return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
}
public static string GetQualifiedName(this ITypeSymbol symbol)
{
return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat).Split(new[] { "::" }, StringSplitOptions.RemoveEmptyEntries).Last();
}
public static string GetMinimallyQualifiedName(this ITypeSymbol symbol)
{
return symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
}
public static bool IsOrdinaryMethod(this IMethodSymbol methodSymbol)
{
return methodSymbol.MethodKind == MethodKind.Ordinary;
}
public static bool IsPublic(this TypeDeclarationSyntax typeDclr)
{
return typeDclr.Modifiers.Any(modifier => modifier.RawKind.Equals(SyntaxFactory.Token(SyntaxKind.PublicKeyword).RawKind));
}
public static bool IsInternal(this TypeDeclarationSyntax typeDclr)
{
var nonInternalModifiers = new List<int>
{
SyntaxFactory.Token(SyntaxKind.PublicKeyword).RawKind,
SyntaxFactory.Token(SyntaxKind.PrivateKeyword).RawKind,
SyntaxFactory.Token(SyntaxKind.ProtectedKeyword).RawKind
};
return !typeDclr.Modifiers.Any(modifier => nonInternalModifiers.Contains(modifier.RawKind));
}
}
}

Просмотреть файл

@ -0,0 +1,71 @@
using Microsoft.CodeAnalysis.CSharp;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Etg.SimpleStubs.CodeGen.Utils
{
static class RoslynUtils
{
public static UsingDirectiveSyntax UsingDirective(string nameSpace)
{
return SF.UsingDirective(SF.IdentifierName(nameSpace));
}
public static IEnumerable<MethodDeclarationSyntax> GetMethodDeclarations(TypeDeclarationSyntax interfaceNode)
{
return interfaceNode.DescendantNodes().OfType<MethodDeclarationSyntax>();
}
public static ParameterSyntax CreateParameter(string type, string name)
{
return SF.Parameter(new SyntaxList<AttributeListSyntax>(), new SyntaxTokenList(), SF.IdentifierName(type), SF.Identifier(new SyntaxTriviaList().Add(SF.Space), name, new SyntaxTriviaList()), null);
}
public static BaseListSyntax BaseList(params string[] names)
{
return SF.BaseList(SF.SeparatedList<BaseTypeSyntax>(names.Select(name => SF.SimpleBaseType(SF.IdentifierName(name)))));
}
public static List<ParameterSyntax> GetMethodParameterSyntaxList(IMethodSymbol methodSymbol)
{
var paramsSyntaxList = new List<ParameterSyntax>();
foreach (IParameterSymbol param in methodSymbol.Parameters)
{
ParameterSyntax paramSyntax = SF.Parameter(SF.Identifier(param.Name)).WithType(SF.ParseTypeName(param.Type.GetFullyQualifiedName()));
paramsSyntaxList.Add(paramSyntax);
}
return paramsSyntaxList;
}
public static List<IMethodSymbol> GetAllMethods(INamedTypeSymbol interfaceType)
{
var methodsToStub = new List<IMethodSymbol>(interfaceType.GetMembers().OfType<IMethodSymbol>());
methodsToStub.AddRange(GetAllInheritedMethods(interfaceType));
return methodsToStub;
}
public static IEnumerable<IMethodSymbol> GetAllInheritedMethods(ITypeSymbol typeSymbol)
{
var methods = new List<IMethodSymbol>();
if (typeSymbol.AllInterfaces.Any())
{
foreach (var baseInterfaceType in typeSymbol.AllInterfaces)
{
methods.AddRange(baseInterfaceType.GetMembers().OfType<IMethodSymbol>());
}
}
return methods;
}
public static SyntaxKind GetVisibilityKeyword(ISymbol stubbedInterface)
{
return stubbedInterface.DeclaredAccessibility ==
Accessibility.Internal ? SyntaxKind.InternalKeyword : SyntaxKind.PublicKeyword;
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Common" version="1.2.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.2.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="1.2.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Workspaces.Common" version="1.2.1" targetFramework="net461" />
<package id="Microsoft.Composition" version="1.0.27" targetFramework="net461" />
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net461" />
<package id="System.Collections" version="4.0.0" targetFramework="net461" />
<package id="System.Collections.Immutable" version="1.1.37" targetFramework="net461" />
<package id="System.Diagnostics.Debug" version="4.0.0" targetFramework="net461" />
<package id="System.Globalization" version="4.0.0" targetFramework="net461" />
<package id="System.IO" version="4.0.0" targetFramework="net461" />
<package id="System.Linq" version="4.0.0" targetFramework="net461" />
<package id="System.Reflection" version="4.0.0" targetFramework="net461" />
<package id="System.Reflection.Extensions" version="4.0.0" targetFramework="net461" />
<package id="System.Reflection.Metadata" version="1.2.0" targetFramework="net461" />
<package id="System.Reflection.Primitives" version="4.0.0" targetFramework="net461" />
<package id="System.Resources.ResourceManager" version="4.0.0" targetFramework="net461" />
<package id="System.Runtime" version="4.0.0" targetFramework="net461" />
<package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net461" />
<package id="System.Runtime.InteropServices" version="4.0.0" targetFramework="net461" />
<package id="System.Text.Encoding" version="4.0.0" targetFramework="net461" />
<package id="System.Text.Encoding.Extensions" version="4.0.0" targetFramework="net461" />
<package id="System.Threading" version="4.0.0" targetFramework="net461" />
</packages>

Просмотреть файл

@ -0,0 +1,29 @@
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SimpleStubs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Etg.SimpleStubs")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.0.1.0")]

Просмотреть файл

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Etg.SimpleStubs
{
public class SequenceContainer<T>
{
private readonly List<SequenceElement<T>> _sequence = new List<SequenceElement<T>>();
public virtual SequenceContainer<T> Repeat(T element, int count)
{
_sequence.Add(new SequenceElement<T>{Element = element, Count = count});
return this;
}
public int CallCount { get; private set; } = 0;
public SequenceContainer<T> Forever(T element)
{
return Repeat(element, int.MaxValue);
}
public SequenceContainer<T> Once(T element)
{
return Repeat(element, 1);
}
public SequenceContainer<T> Twice(T element)
{
return Repeat(element, 2);
}
public virtual T Next
{
get
{
lock (_sequence)
{
if (!_sequence.Any())
{
throw new SequenceContainerException(
$"The stub sequence has been called more than expected; Make sure the {nameof(SequenceContainer<T>)} is setup correclty");
}
var se = _sequence[0];
T e = se.Element;
if (--se.Count == 0)
{
_sequence.RemoveAt(0);
}
CallCount++;
return e;
}
}
}
private class SequenceElement<TElement>
{
public TElement Element
{
get;
set;
}
public int Count
{
get;
set;
}
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
using System;
namespace Etg.SimpleStubs
{
public class SequenceContainerException : Exception
{
public SequenceContainerException(string msg) : base(msg)
{
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C1AAD08E-2A69-429C-8AFF-142B468E0A8F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Etg.SimpleStubs</RootNamespace>
<AssemblyName>Etg.SimpleStubs</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<None Include="project.json" />
<!-- A reference to the entire .NET Framework is automatically included -->
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SequenceContainer.cs" />
<Compile Include="SequenceContainerException.cs" />
<Compile Include="StubsUtils.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,10 @@
namespace Etg.SimpleStubs
{
public static class StubsUtils
{
public static SequenceContainer<T> Sequence<T>()
{
return new SequenceContainer<T>();
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
{
"supports": {
"net46.app": {},
"uwp.10.0.app": {},
"dnxcore50.app": {}
},
"dependencies": {
"Microsoft.NETCore": "5.0.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.0"
},
"frameworks": {
"dotnet": {
"imports": "portable-net452+win81"
}
}
}

Просмотреть файл

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace TestClassLibrary
{
public interface IAppConfigPeriodicRefreshHandler : IDisposable
{
void Start();
}
public interface IPhoneBook
{
long GetContactPhoneNumber(string firstName, string lastName);
long MyNumber { get; set; }
int ContactsCount { get; }
event EventHandler<long> PhoneNumberChanged;
}
public interface ITestInterface : IDisposable
{
void DoSomething(string s, int x);
void DoSomething(List<IEnumerable<string>> list);
void DoSomething(string[] array);
Task<List<int>> DoSomething(int parameter);
string Prop1 { get; }
string Prop2 { set; }
string Prop3 { get; set; }
event EventHandler<EventArgs> Changed;
event EventHandler OtherEvent;
List<T> GetGenericList<T, A>();
void SetGenericValue<T>(T value);
}
public interface IIgnoredInterface : IDisposable
{
}
interface IInternalInterface
{
void DoSomethingInternal();
}
public interface IGenericInterface<T>
{
T GetX();
}
}

Просмотреть файл

@ -0,0 +1,38 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TestClassLibrary")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestClassLibrary")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ecbcbae6-949e-4e9c-84e1-614d97909b6c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("TestClassLibraryTest")]

Просмотреть файл

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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>{ECBCBAE6-949E-4E9C-84E1-614D97909B6C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestClassLibrary</RootNamespace>
<AssemblyName>TestClassLibrary</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<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" />
</ItemGroup>
<ItemGroup>
<Compile Include="ITestInterface.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,10 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="Etg.SimpleStubs.CodeGen.Tasks.GenerateStubsTask" AssemblyFile="$(ProjectDir)SimpleStubsDlls\Etg.SimpleStubs.CodeGen.dll" />
<Target Name="BeforeBuild">
<ItemGroup>
<SimpleStubsDlls Include="$(ProjectDir)..\..\src\SimpleStubs.CodeGen\bin\$(ConfigurationName)\**\*.dll" />
</ItemGroup>
<Copy SourceFiles="@(SimpleStubsDlls)" DestinationFolder="$(ProjectDir)SimpleStubsDlls\%(RecursiveDir)" ContinueOnError="true" Retries="0"/>
<GenerateStubsTask ProjectPath="$(ProjectDir)$(ProjectName).csproj" OutputPath="$(ProjectDir)Properties\SimpleStubs.generated.cs" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TestClassLibraryTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestClassLibraryTest")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("cb81f60f-1374-4b46-bb64-d848b5103a58")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,10 @@
{
"IgnoredProjects": [
"SimpleStubs",
"SimpleStubs.CodeGen"
],
"IgnoredInterfaces": [
"TestClassLibrary.IIgnoredInterface"
],
"StubInternalInterfaces": true
}

Просмотреть файл

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{CB81F60F-1374-4B46-BB64-D848B5103A58}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestClassLibraryTest</RootNamespace>
<AssemblyName>TestClassLibraryTest</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.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>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\..\packages\Autofac.3.5.2\lib\net40\Autofac.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Build.Utilities.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<Reference Include="Microsoft.CodeAnalysis, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.CSharp.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.1.1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.Workspaces, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.1.1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.37.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.AttributedModel, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.Convention, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.Hosting, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.Runtime, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Composition.TypedParts, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reflection.Metadata, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reflection.Metadata.1.1.0\lib\dotnet5.2\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="Properties\SimpleStubs.generated.cs" />
<Compile Include="UnitTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\SimpleStubs.CodeGen\SimpleStubs.CodeGen.csproj">
<Project>{3e9c520a-94cf-46d0-864b-4293d439c92a}</Project>
<Name>SimpleStubs.CodeGen</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\SimpleStubs\SimpleStubs.csproj">
<Project>{c1aad08e-2a69-429c-8aff-142b468e0a8f}</Project>
<Name>SimpleStubs</Name>
</ProjectReference>
<ProjectReference Include="..\TestClassLibrary\TestClassLibrary.csproj">
<Project>{ecbcbae6-949e-4e9c-84e1-614d97909b6c}</Project>
<Name>TestClassLibrary</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="SimpleStubs.json" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ImportGroup>
<Import Project="Etg.SimpleStubs.targets" Condition="Exists('Etg.SimpleStubs.targets')" />
</ImportGroup>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,115 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Etg.SimpleStubs;
using Etg.SimpleStubs.CodeGen;
using Etg.SimpleStubs.CodeGen.DI;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestClassLibrary;
namespace TestClassLibraryTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethodWithReturnTypeAndParameters()
{
long number = 6041234567;
string firstName = null;
string lastName = null;
var stub = new StubIPhoneBook
{
GetContactPhoneNumber_String_String = (fn, ln) =>
{
firstName = fn;
lastName = ln;
return number;
}
};
IPhoneBook phoneBook = stub;
long actualNumber = phoneBook.GetContactPhoneNumber("John", "Smith");
Assert.AreEqual(number, actualNumber);
Assert.AreEqual("John", firstName);
Assert.AreEqual("Smith", lastName);
}
[TestMethod]
public void TestPropertyStubWithGetterAndSetter()
{
long myNumber = 6041234567;
long newNumber = 0;
var stub = new StubIPhoneBook
{
MyNumber_Get = () => myNumber,
MyNumber_Set = num =>
{
newNumber = num;
}
};
IPhoneBook phoneBook = stub;
Assert.AreEqual(myNumber, phoneBook.MyNumber);
phoneBook.MyNumber = 13;
Assert.AreEqual(13, newNumber);
}
[TestMethod]
public void TestPropertyStubWithGetterOnly()
{
int contactsCount = 55;
var stub = new StubIPhoneBook { ContactsCount_Get = () => contactsCount };
IPhoneBook phoneBook = stub;
Assert.AreEqual(contactsCount, phoneBook.ContactsCount);
}
[TestMethod]
public void TestEventStub()
{
object sender = null;
long newNumber = 0;
var stub = new StubIPhoneBook();
stub.PhoneNumberChanged += (s, num) =>
{
sender = s;
newNumber = num;
}
;
stub.PhoneNumberChanged_Raise(this, 55);
Assert.AreEqual(55, newNumber);
Assert.AreEqual(this, sender);
}
[TestMethod]
public void TestCallSequence()
{
var sequence = StubsUtils.Sequence<Func<string, string, int>>()
.Once((p1, p2) => 12345678) // first call
.Repeat((p1, p2) => 11122233, 2) // next two call
.Forever((p1, p2) => 22233556); // rest of the calls
var stub = new StubIPhoneBook { GetContactPhoneNumber_String_String = (p1, p2) => sequence.Next(p1, p2) };
IPhoneBook phoneBook = stub;
Assert.AreEqual(12345678, phoneBook.GetContactPhoneNumber("John", "Smith"));
Assert.AreEqual(11122233, phoneBook.GetContactPhoneNumber("John", "Smith"));
Assert.AreEqual(11122233, phoneBook.GetContactPhoneNumber("John", "Smith"));
Assert.AreEqual(22233556, phoneBook.GetContactPhoneNumber("John", "Smith"));
Assert.AreEqual(22233556, phoneBook.GetContactPhoneNumber("John", "Smith"));
Assert.AreEqual(22233556, phoneBook.GetContactPhoneNumber("John", "Smith"));
Assert.AreEqual(6, sequence.CallCount);
}
// this test is only used for debugging
[Ignore]
[TestMethod]
public async Task TestGenerateStubs()
{
string path = //@"C:\projects\JasperMain\Product\Jasper.Test\Jasper.Test.csproj";
@"..\..\TestClassLibraryTest.csproj";
//"..\\..\\SimpleStubsTest.csproj";
SimpleStubsGenerator stubsGenerator = new DiModule(path, @"..\..\Properties\SimpleStubs.generated.cs").StubsGenerator;
string stubs = await stubsGenerator.GenerateStubs(path);
File.WriteAllText(@"..\..\Properties\SimpleStubs.generated.cs", stubs);
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Common" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.CodeAnalysis.Workspaces.Common" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Composition" version="1.0.27" targetFramework="net461" />
<package id="System.Collections" version="4.0.0" targetFramework="net461" />
<package id="System.Collections.Immutable" version="1.1.37" targetFramework="net461" />
<package id="System.Diagnostics.Debug" version="4.0.0" targetFramework="net461" />
<package id="System.Globalization" version="4.0.0" targetFramework="net461" />
<package id="System.IO" version="4.0.0" targetFramework="net461" />
<package id="System.Linq" version="4.0.0" targetFramework="net461" />
<package id="System.Reflection" version="4.0.0" targetFramework="net461" />
<package id="System.Reflection.Extensions" version="4.0.0" targetFramework="net461" />
<package id="System.Reflection.Metadata" version="1.1.0" targetFramework="net461" />
<package id="System.Reflection.Primitives" version="4.0.0" targetFramework="net461" />
<package id="System.Resources.ResourceManager" version="4.0.0" targetFramework="net461" />
<package id="System.Runtime" version="4.0.0" targetFramework="net461" />
<package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net461" />
<package id="System.Runtime.InteropServices" version="4.0.0" targetFramework="net461" />
<package id="System.Text.Encoding" version="4.0.0" targetFramework="net461" />
<package id="System.Text.Encoding.Extensions" version="4.0.0" targetFramework="net461" />
<package id="System.Threading" version="4.0.0" targetFramework="net461" />
</packages>