C# Unit Test Getting Started with Complete Code

This article is a supplement of the basic introduction of C# Unit Test from MSDN. As you may find, although technically correct, the MSDN article is confusing here and there, probably because it was written by several people with different assumptions. Another defect of the MSDN article is that the code samples are either too much – so it cannot focus on the point, or too little – so it loses its connection with other essential parts of a complete Unit Test solution. That’s why I am writing this article, with complete code sample tested in VS2013 that you can download.

There are three Sections of this article, with three corresponding VS solutions in the code sample: Basic Unit Test, Unit Test with Stub, and Unit Test with Shim. You should follow the order if you are new to this topic.

Basic Unit Test

Please read the MSDN Unit Test Basics article first, EXCEPT the “Additional tools” section. And refer the “UnitTest” sample in my code.

Note that there are only two projects in the VS solution: Accounts project with only one code class CheckingAccount.cs, and AccountsTest project with only one test class CheckingAccountTest.cs. The mention of BankDB and BankDBTest projects, as well as other interfaces or classes in the MSDN article should all be ignored for now.

Now it should be easy to get the point of Unit Test.

Unit Test with Stub

Now go back to read the “Additional tools” section of the MSDN Unit Test Basics article, esp. the last part “Isolating unit test methods with Microsoft Fakes”. Does it make much sense? I would not be suprised if you think it doesn’t. In fact, there are even errors in the code samples in this part: “var stubBankDb = new MyBank.Stubs.StubIBankDb();” is from an older version of Microsoft Fakes (called Microsoft Moles, just in case you are wondering). In VS2013 it should be “var stubBankDb = new MyBank.Fakes.StubIBankDb();”. Now you understand what I was talking about at the beginning of this article.

OK. Now go ahead and read the MSDN Microsoft Fakes article. This one should make much more sense. And refer to the “UnitTestWithStub” sample in my code.

The addition of a new project BankDB represents a different component that introduces other dependencies, like network connection, database connection, certian files that should be available in the client’s computer on runtime, etc. This is where Stubs are supposed to work. Note that the code samples in the MSDN Fakes article are no longer the Bank/Account ones, while I am still keeping the same context in my code sample.

If you try to follow the article by clicking “Add Fakes Assembly”, you will find the following error message. Deleting the reference is not enough, you may need to delete the Fakes\BankDb.fakes file as well.

7-16-2015 3-12-39 PM

Unit Test with Shim 

The Shim sample code should be pretty straight forward. It’s basically highjacking a call to an external reference and return a preset value.

One problem is that VS2013 Shim generation with System reference seems to be not working well with .net Framework 4.5(.x), with a strange error regarding System.Security.Cryptography. Changing the target framework to 4.6 would work. Or, try VS2015.

sqlite3.def for 3.8.6

EXPORTS
sqlite3_aggregate_context
sqlite3_aggregate_count
sqlite3_auto_extension
sqlite3_backup_finish
sqlite3_backup_init
sqlite3_backup_pagecount
sqlite3_backup_remaining
sqlite3_backup_step
sqlite3_bind_blob

sqlite3_bind_double
sqlite3_bind_int
sqlite3_bind_int64
sqlite3_bind_null
sqlite3_bind_parameter_count
sqlite3_bind_parameter_index
sqlite3_bind_parameter_name
sqlite3_bind_text
sqlite3_bind_text16

sqlite3_bind_value
sqlite3_bind_zeroblob
sqlite3_blob_bytes
sqlite3_blob_close
sqlite3_blob_open
sqlite3_blob_read
sqlite3_blob_reopen
sqlite3_blob_write
sqlite3_busy_handler
sqlite3_busy_timeout
sqlite3_cancel_auto_extension
sqlite3_changes
sqlite3_clear_bindings
sqlite3_close
sqlite3_close_v2
sqlite3_collation_needed
sqlite3_collation_needed16
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_bytes16
sqlite3_column_count
sqlite3_column_decltype
sqlite3_column_decltype16
sqlite3_column_double
sqlite3_column_int
sqlite3_column_int64
sqlite3_column_name
sqlite3_column_name16
sqlite3_column_text
sqlite3_column_text16
sqlite3_column_type
sqlite3_column_value
sqlite3_commit_hook
sqlite3_compileoption_get
sqlite3_compileoption_used
sqlite3_complete
sqlite3_complete16
sqlite3_config
sqlite3_context_db_handle
sqlite3_create_collation
sqlite3_create_collation16
sqlite3_create_collation_v2
sqlite3_create_function
sqlite3_create_function16
sqlite3_create_function_v2
sqlite3_create_module
sqlite3_create_module_v2
sqlite3_data_count
sqlite3_db_config
sqlite3_db_filename
sqlite3_db_handle
sqlite3_db_mutex
sqlite3_db_readonly
sqlite3_db_release_memory
sqlite3_db_status
sqlite3_declare_vtab
sqlite3_enable_load_extension
sqlite3_enable_shared_cache
sqlite3_errcode
sqlite3_errmsg
sqlite3_errmsg16
sqlite3_errstr
sqlite3_exec
sqlite3_expired
sqlite3_extended_errcode
sqlite3_extended_result_codes
sqlite3_file_control
sqlite3_finalize
sqlite3_free
sqlite3_free_table
sqlite3_get_autocommit
sqlite3_get_auxdata
sqlite3_get_table
sqlite3_global_recover
sqlite3_initialize
sqlite3_interrupt
sqlite3_last_insert_rowid
sqlite3_libversion
sqlite3_libversion_number
sqlite3_limit
sqlite3_load_extension
sqlite3_log
sqlite3_malloc

sqlite3_memory_alarm
sqlite3_memory_highwater
sqlite3_memory_used
sqlite3_mprintf

sqlite3_mutex_alloc
sqlite3_mutex_enter
sqlite3_mutex_free
sqlite3_mutex_leave
sqlite3_mutex_try
sqlite3_next_stmt
sqlite3_open
sqlite3_open16
sqlite3_open_v2
sqlite3_os_end
sqlite3_os_init
sqlite3_overload_function
sqlite3_prepare
sqlite3_prepare16
sqlite3_prepare16_v2
sqlite3_prepare_v2
sqlite3_profile
sqlite3_progress_handler
sqlite3_randomness
sqlite3_realloc

sqlite3_release_memory
sqlite3_reset
sqlite3_reset_auto_extension
sqlite3_result_blob

sqlite3_result_double
sqlite3_result_error
sqlite3_result_error16
sqlite3_result_error_code
sqlite3_result_error_nomem
sqlite3_result_error_toobig
sqlite3_result_int
sqlite3_result_int64
sqlite3_result_null
sqlite3_result_text
sqlite3_result_text16
sqlite3_result_text16be
sqlite3_result_text16le

sqlite3_result_value
sqlite3_result_zeroblob
sqlite3_rollback_hook
sqlite3_set_authorizer
sqlite3_set_auxdata
sqlite3_shutdown
sqlite3_sleep
sqlite3_snprintf
sqlite3_soft_heap_limit
sqlite3_soft_heap_limit64
sqlite3_sourceid
sqlite3_sql
sqlite3_status

sqlite3_step
sqlite3_stmt_busy
sqlite3_stmt_readonly
sqlite3_stmt_status
sqlite3_strglob
sqlite3_stricmp
sqlite3_strnicmp

sqlite3_test_control
sqlite3_thread_cleanup
sqlite3_threadsafe
sqlite3_total_changes
sqlite3_trace
sqlite3_transfer_bindings
sqlite3_update_hook
sqlite3_uri_boolean
sqlite3_uri_int64
sqlite3_uri_parameter
sqlite3_user_data
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_bytes16
sqlite3_value_double
sqlite3_value_int
sqlite3_value_int64
sqlite3_value_numeric_type
sqlite3_value_text
sqlite3_value_text16
sqlite3_value_text16be
sqlite3_value_text16le
sqlite3_value_type
sqlite3_vfs_find
sqlite3_vfs_register
sqlite3_vfs_unregister
sqlite3_vmprintf
sqlite3_vsnprintf
sqlite3_vtab_config
sqlite3_vtab_on_conflict
sqlite3_wal_autocheckpoint
sqlite3_wal_checkpoint
sqlite3_wal_checkpoint_v2
sqlite3_wal_hook
sqlite3_win32_is_nt
sqlite3_win32_mbcs_to_utf8
sqlite3_win32_set_directory
sqlite3_win32_sleep
sqlite3_win32_utf8_to_mbcs
sqlite3_win32_write_debug

ClickOnce with Visual C++ 2010 Runtime Libraries (x86) Prerequisite

This article applies to Visual Studio 2010 SP1.

ClickOnce provides a nice utility to include prerequisites in the deployment. But the VC++ Runtime x86 shipped with VS is bugged. As a result, the ClickOnce installer will try to download and install the VC++ Runtime all the time. And most of the times, this installation will fail because it finds that a newer version has already been installed.

There are in fact two things going wrong here:

1) The installer tries to detect the installed VC++ Runtime with a wrong product code. So when it cannot find the wrong code, it thinks the VC++ Runtime is not installed and tries to download one.

2) It uses a wrong download link to download the older version of the runtime, which would fail if you already has a newer one.

Fixes:

1) Go to C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\vcredist_x86\product.xml. Find this section:

<InstallChecks>
 <MsiProductCheck Property="VCRedistInstalled" Product="{6EE91C1A-A2E7-38CD-AEBB-3B900A4D8868}"/>
</InstallChecks>

The product code needs to be changed to {F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.

2) Go to C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\vcredist_x86\en\package.xml. Find this section:

<String Name="VCRedistExe">http://go.microsoft.com/fwlink/?LinkID=177916&amp;clcid=0x409</String>

The LinkID needs to be changed to 210621.

 

references:

http://stackoverflow.com/questions/7785328/visual-c-2010-runtime-libraries-prerequisite-keeps-popping-up-on-a-vs-2010-cre

https://connect.microsoft.com/VisualStudio/feedback/details/726264/msdn-forum-vcredist-x86-bootstrapper-package-xml-content-wrong

“-529697949 (0xe06d7363) Microsoft C++ Exception” with Revit 2015+ API

ERROR: “The program Revit.exe has exited with code -529697949 (0xe06d7363) Microsoft C++ Exception.”

I guess while developing with Revit 2015+ API, you hit this error when you are trying to start Revit in VS to debug? You may want to go to VS – Tools – Options – Debugging, simply check “Use Managed Compatibility Mode”. And try again. Good luck!

4-21-2014 3-28-30 PM

4-21-2014 4-58-58 PM

EXTERNAL COMMAND IN 10 STEPS FOR REVIT 2015/2016 API

This is not yet another getting started tutorial on Revit API, but rather a concise checklist and minimum development environment that one can test and verify the system is working before diving into more complex code.

0. the prerequisites:

Make sure Revit 2015/2016 and Visual Studio 2012/2013 is installed. Revit 2015 will not work with older Visual Studios.

1. the project:

Create a new “Class Library” project in “Visual C#” with “.NET Framework 4.5”.

2. the references:

Add RevitAPI.dll, RevitAPIUI.dll and System.Windows.Forms as project references.

Change the “Copy Local” property of RevitAPI.dll and RevitAPIUI.dll to false.

3. the class:

Inherit the Autodesk.Revit.UI.IExternalCommand interface.

Add the following class attribute code before the class declaration.

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Automatic)]

4. the method:

Implement the Execute method of the inherited interface.

public Autodesk.Revit.UI.Result Execute(
    Autodesk.Revit.UI.ExternalCommandData commandData,
    ref string message,
    Autodesk.Revit.DB.ElementSet elements)
{
    System.Windows.Forms.MessageBox.Show("Hello World");
    return Autodesk.Revit.UI.Result.Succeeded;
} 

5. the assembly:

Press F6 and VS should report “Build succeeded”.

Note the output path of the dll file shown in the Output window.

6. the GUID:

Create a unique ID for your command.

7. the .addin file

Create an empty text file in: C:\Users\yourUserName\AppData\Roaming\Autodesk\Revit\Addins\201X

(or C:\ProgramData\Autodesk\Revit\Addins\201X).

Change the file name to anyNameWillWork.addin.

Open the file and copy or type the following code:

<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
    <AddIn Type="Command">
        <Assembly>C:\yourAddinPath\youAddinName.dll</Assembly>
        <AddInId>yourLong-Long-Long-Long-GuidGoesHere</AddInId>
        <FullClassName>yourAddinNamespace.YourAddinClassName</FullClassName>
        <Text>ExternalCommandTest</Text>
        <VendorId>LZNT</VendorId>
    </AddIn>
</RevitAddIns>

8. DONE!

Now start Revit and you should see an “Add-Ins” tab at the end of Revit tabs, in which there is an “External Tools” button with the newly created External Command.

9. (optional) the debugging:

Point the “Start external program” to the installed revit.exe.

Go to Tools – Options – Debugging, check “Use Managed Compatibility Mode”.

Set a break point in your code.

Press F5 in VS and Revit should be started.

Activate your plugin and you break point should be hit.

~~~~~~~~~~END of original post~~~~~~~~~~

~~~~~~~~~~Update 2015.5.15~~~~~~~~~~

GitHub: 

A GitHub repository is created, with the complete Test project for Revit 2016 API. The only thing you need to do is edit the Assembly line in the .addin file, and copy the file to your Revit Addins folder. You are welcome to download the code, and let me know if there are any questions and problems. Enjoy!

https://github.com/lezhangnet/RevitAPI

Reference:

As mentioned at the beginning of this post, the content in this post is as concise as possible. If you want more information, here is a tutorial from Autodesk Revit API documentation that contains more details. You may also find the other parts of the documentation to be useful when you try to dig dipper.

http://help.autodesk.com/view/RVT/2016/ENU/?guid=GUID-8EB25D2A-3CAF-486A-BA8E-C2BEF3DB68F6

“Customization could not be loaded” error with VSTO

ERROR: “Customization could not be loaded because the application domain could not be created.”

If you are working on an Excel (or other Office, I guess) VSTO AddIn / PlugIn project using C# and encountered this error, you may want to check that you are using the right platform (x86 vs x64) in your Configuration Manager.

I have x64 Office 2010 installed and saw this error when I am trying to run the x86 plugin today.

3-28-2014 4-17-19 PM

Pursuing IT with eager feet …